배열이란 무엇인가
배열이 무엇인지부터 자바에서의 선언, 생성, 사용법, 주의할 점까지 예제와 함께 정리한 학습 글이다.
1. 배열이란?
배열(Array)은 같은 자료형의 값을 여러 개 묶어서 전장하는 구조이다.
예를 들어 학생 점수 5개를 저장해야 한다고 하면, 변수 5개를 따로 만드는 대신 배열 하나로 관리할 수 있게된다.
자바 배열은 인덱스(index) 로 각 값을 구분하며, 인덱스는 0부터 시작한다.
또 한 번 생성하게 되면 크기를 바꿀 수 없다는 점이 핵심 특징이다.
처음 배열을 배울 때는 그냥 “값 여러 개 넣는 통”처럼 보이는데, 실제로는 단순 저장 이상의 의미가 있다.
배열은 데이터를 순서 있게 보관하고, 같은 타입끼리 일관성 있게 처리하게 해준다. 그래서 반복문과 함께 쓰이면 굉장히 강력하다.
예를 들어 점수를 관리한다고 해보자.
1
int[] scores = {88, 92, 75, 64, 100};
이제 scores[0], scores[1]처럼 각 값에 접근할 수 있다.
즉, 배열은 “여러 값을 하나의 이름 아래에서 관리하는 방식”이라고 보면 된다.
2. 배열은 어떻게 선언하고 생성하는가
배열을 사용할 때는 보통 선언 → 생성 → 초기화 흐름으로 이해하면 쉽다.
배열 선언은 “이런 타입의 배열을 쓰겠다”는 뜻이고, 생성은 “실제로 몇 칸짜리 공간을 만들겠다”는 뜻이다.
선언만 하면 아직 저장 공간은 없는 상태고, new를 사용해야 실제 배열이 만들어진다.
자바에서 배열은 new로 생성되며, 생성 후 크기는 고정된다. 또한 기본형 배열의 값은 0, boolean은 false, 참조형은 null로 자동 초기화된다.
예를 들어
1
2
int[] numbers; // 선언
numbers = new int[4]; // 생성
이렇게 하면 정수 4개를 저장할 수 있는 배열이 만들어진다.
이 시점의 numbers안에는 아직 내가 넣은 값은 없지만, 자바가 기본으로 채워 넣는다.
1
2
System.out.println(numbers[0]); // 0
System.out.println(numbers[1]); // 0
이 부분에서 중요한 건, 배열은 생성 순간 크기가 정해진다는 점이다.
즉, new int[4]로 만들면 끝가지 4칸짜리가 되는 것이다. 나중에 값이 더 필요하다고 해서 자동으로 늘어나지 않는다.
이 특성은 장점과 단점이 동시에 존재한다.
- 장점: 구조가 단순하고 예측 가능하다.
- 단점: 유연하게 늘어나지 않는다.
그래서 배열은 “개수가 정해진 데이터”를 다룰 때 특히 잘 맞는다.
3. 배열을 실제로 어떻게 사용하는가
배열의 핵심 사용법은 크게 세 가지다.
- 값 넣기
- 값 꺼내기
- 전체 순회하기
배열의 요소는 인덱스로 접근하고 수정할 수 있으며, 전체 요소를 다룰 때는 반복문과 length를 함께 사용한다.
배열의 크기는 length로 확인한다.
3-1. 값 넣기와 꺼내기
1
2
3
4
5
6
String[] menu = new String[3];
menu[0] = "김치찌개";
menu[1] = "된장찌개";
menu[2] = "순두부찌개";
System.out.println(menu[1]); // 된장찌개
여기서 menu[1]은 두 번째 요소이다.
배열은 1부터가 아닌 0부터 시작하므로, 이 부분은 처음 배우게 된다면 헷갈릴 수 있다.
3-2. 값 수정하기
1
2
menu[2] = "부대찌개";
System.out.println(menu[2]); // 부대찌개
배열은 크기를 못 바꾸지만, 기존 칸의 값은 바꿀 수 있다.
3-3. 전체 순회하기
배열을 쓰는 진짜 이유는 반복문을 만났을 때 드러난다.
1
2
3
4
5
int[] nums = {3, 6, 8, 12};
for (int i = 0; i < nums.length; i++) {
System.out.println(nums[i]);
}
여기서 nums.length는 배열 길이이고, 인덱스 범위는 0부터 length - 1까지다.
즉 길이가 4면 인덱스는 0, 1, 2, 3이 된다.
배열을 반복문으로 순회하는 건 합계, 평균, 최댓값, 최소값처럼 여러 값을 한 번에 계산하는 기본 패턴이 여기서 시작된다고 보면 된다.
예를 들면
1
2
3
4
5
6
7
8
int[] scores = {80, 90, 100};
int sum = 0;
for (int i = 0; i < scores.length; i++) {
sum += scores[i];
}
System.out.println("총합: + sum");
배열은 단순 문법이 아닌, 반복 처리의 출발점이라고 보는 게 좋을 것 같다.
4. 배열을 공부할 때 꼭 이해해야 하는 핵심 포인트
배열은 문법 자체는 어렵지 않지만, 몇 가지를 정확히 이해하지 않으면 계속 헷갈릴 수 있다.
4-1. 배열의 길이와 마지막 인덱스는 다르다
💡중요
1
int[] arr = new int[5];
이 배열의 길이는 5이지만, 마지막 인덱스는 5가 아닌 4가 된다.
왜냐하면 시작이 0이기 때문이다.
- 첫 번째 칸 →
arr[0] - 두 번째 칸 →
arr[1] - 세 번째 칸 →
arr[2] - 네 번째 칸 →
arr[3] - 다섯 번째 칸 →
arr[4]
4-2. 범위를 벗어나면 예외가 발생한다
자바 배열은 존재하지 않는 칸에 접근하면 ArrayIndexOutOfBoundsException이 발생한다.
즉 인덱스가 음수이거나, 배열 길이 이상이면 오류가 난다.
예시
1
2
int[] arr = {10, 20, 30};
System.out.println(arr[3]); // 예외 발생
유효한 인덱스는 0, 1, 2뿐인데 3에 접근했기 때문이다.
이 예외가 자주 발생하는 이유는 보통 두 가지다.
- 반복문 조건을 잘못 쓴 경우
- 배열 길이와 인덱스를 혼동한 경우
그래서 배열을 다룰 때는 항상 이 기준을 머릿속에 넣어두면 좋다.
1
0 <= index < arr.length
4-3. 배열은 같은 타입만 저장할 수 있다
배열은 같은 자료형만 저장한다.
즉 정수 배열에는 정수만 넣어야 하고, 문자열 배열에는 문자열만 넣어야 한다.
1
2
int[] arr = {1, 2, 3}; // 가능
String[] names = {"철수", "영희"}; // 가능
하지만 아래처럼 섞어 놓는 개념은 허용되지 않는다.
1
2
// 불가능한 개념
// int[] arr = {1, "hello", 3};
이 특징은 불편해 보일 수도 있지만, 반대로 생각하면 타입이 명확해서 코드가 안정적이다.
4-4. 객체 배열은 객체 자체가 아니라 참조를 저장한다
배열에는 기본형뿐 아니라 객체도 담을 수 있다.
그런데 객체 배열은 객체를 통쨰로 저장한느 게 아니라 객체를 가리키는 참조값을 저장한다.
예를 들어
1
2
3
4
5
6
7
class Student {
String name;
Student(String name) {
this.name = name;
}
}
1
2
3
Student[] students = new Student[2];
students[0] = new Student("민수");
students[1] = new Student("지연");
여기서 new Student[2]는 Student객체 2개를 만든 것이 아닌, Student를 참조할 수 있는 칸 2개를 만든 것이다.
그래서 각 칸에 다시 new Student(...)를 넣어줘야 한다.
이 부분을 놓치면 아래 같은 실수를 하게 된다.
1
2
Student[] students = new Student[2];
System.out.println(students[0].name); // null 관련 오류 가능
왜냐하면 아직 students[0]에 실제 Student 객체를 넣지 않았기 때문이다.
5. 배열과 메서드는 어떻게 연결되는가
배열은 변수처럼 메서드에 전달할 수 있고, 메서드에서 배열을 반환할 수도 있다.
이것은 배열을 단순 저장 용도가 아닌, 기능 단위로 분리해서 처리할 수 있게 해준다는 점에서 중요하다.
예를 들어 배열의 총합을 구하는 메서드를 만들 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Main {
public static void main(String[] args) {
int[] prices = {1000, 2000, 3000};
printTotal(prices);
}
public static void printTotal(int[] arr) {
int total = 0;
for (int i = 0; i < arr.length; i++) {
total += arr[i];
}
System.out.println("총합: " + total);
}
}
이렇게 하면 배열을 직접 처리하는 로직을 메서드로 분리할 수 있다.
즉, 코드가 더 읽기 쉬워지고 재사용하기도 쉬워진다.
반대로 메서드가 배열을 만들어서 반환할 수도 있다.
1
2
3
public static int[] makeArray() {
return new int[]{1, 2, 3, 4};
}
이런 방식은 여러 값을 한 번에 전달하고 싶을 때 유용하다.
6. 배열의 장점과 한계
배열은 가장 기본적인 자료구조인 만큼 장점도 분명하고 한계도 분명하다.
배열의 장점은 인덱스로 바로 접근할 수 있고 빠르다는 점이고, 단점은 크기가 고정되어 있고 중간 삽입/삭제가 비효율적이라는 점이다.
장점
- 인덱스로 바로 접근하므로 속도가 빠름
- 예) 100개의 값이 있어도
arr[50]처럼 바로 접근할 수 있다.
- 예) 100개의 값이 있어도
- 반복문과 궁합이 좋다.
- 합계, 평균, 탐색, 최댓값 찾기 같은 문제를 다룰 때 배열은 거의 필수적이다.
단점
- 크기가 고정된다.
- 처음에 너무 작게 만들면 부족하고, 너무 크게 만들면 공간이 남게된다.
- 중간 삽입/삭제가 불편하다.
- 예) 중간에 값을 끼워 넣으려면 뒤 요소들은 한 칸씩 밀어야 한다.
위와 같은 이유들로 배열과 ArrayList를 상황에 맞게 구분해서 사용한다.
정리
배열은 자바에서 가장 먼저 배우는 자료구조이지만, 뒤로 갈수록 더 중요해지는 것 같다.
반복문, 객체, 메서드, 자료구조, 알고리즘까지 전부 배열 개념 위에서 확장되기 때문이다.
배열을 공부하면서 꼭 잡아야 할 핵심은 아래와 같다고 생각한다.
- 배열은 같은 타입의 값을 묶어 저장한다.
- 인덱스는 0부터 시작한다.
- 생성 후 크기는 바꿀 수 없다.
length로 길이를 확인한다.- 반복문과 함께 많이 사용한다.
- 객체 배열은 참조를 저장한다.
- 범위를 벗어나면 예외가 발생한다.
이 정도를 정확히 이해한다면, ArrayList, 2차원 배열, 자료구조 문제도 수월해질거라 생각한다.