Java 배열 .length 설명: 예제와 함께하는 완전 가이드
Source: Dev.to
Java 배열에서 .length는 정확히 무엇일까?
Java에서 배열은 단일 타입의 값을 고정된 개수만큼 담는 컨테이너 객체입니다.
.length는 final 필드(메서드가 아님)로, 그 컨테이너의 용량을 알려줍니다.
int[] myNumbers = new int[5]; // 5개의 슬롯을 가진 배열 생성
System.out.println(myNumbers.length); // 출력: 5
Note: 괄호가 없습니다 –
.length는 메서드가 아니라 속성입니다.String.length()에 익숙한 초보자들이 흔히 혼동합니다.
세부 사항: .length가 실제로 동작하는 방식
Java에서 배열은 객체입니다. 배열이 생성될 때 Java는 연속된 메모리 블록을 할당하고 .length 필드를 설정합니다. 이 값은 변경할 수 없으며, 그래서 배열은 고정 크기를 갖습니다.
String[] playlist = new String[10]; // .length는 이제 10, 영원히
playlist[0] = "Track 1";
playlist[9] = "Last track";
// 실제로 채우는 개수와 관계없이 이 배열은 10개의 슬롯을 가집니다
실제 코딩 예시
예시 1: 고전적인 루프
// 게임에서 사용자 점수 처리
int[] highScores = {1250, 980, 1540, 720, 2100};
for (int i = 0; i < highScores.length; i++) {
System.out.println("Player " + (i + 1) + " score: " + highScores[i]);
}
ArrayIndexOutOfBoundsException을 피하려면 루프 경계에 항상 highScores.length를 사용하세요.
예시 2: 현대적인 for‑each 대안
// 향상된 for 루프로 더 깔끔하게
for (int score : highScores) {
System.out.println("Score: " + score);
}
향상된 for‑loop는 내부적으로 .length를 사용하므로 수동 경계 검사를 하지 않아도 됩니다.
예시 3: 배열 용량 검증
// 배열을 직접 관리할 때 추가하기 전에
int[] dataBuffer = new int[1000];
int currentPosition = 0;
public void addData(int value) {
if (currentPosition < dataBuffer.length) {
dataBuffer[currentPosition++] = value;
} else {
System.out.println("Buffer full! Can't add more.");
}
}
흔히 저지르는 실수와 함정
실수 1: String과 배열 혼동
String name = "Java";
String[] languages = {"Java", "Python", "JavaScript"};
System.out.println(name.length()); // 메서드 – 괄호 필요
System.out.println(languages.length); // 필드 – 괄호 없음
암기법: 배열 → 괄호 없음; 문자열 → 괄호 필요.
실수 2: Null 포인터
int[] myArray = null;
System.out.println(myArray.length); // NullPointerException 발생!
.length에 접근하기 전에 배열이 null인지 항상 확인하세요.
실수 3: 다차원 배열
int[][] matrix = new int[3][4];
System.out.println(matrix.length); // 3 (행)
System.out.println(matrix[0].length); // 4 (첫 번째 행의 열)
.length는 첫 번째 차원의 크기만 반환합니다.
전문가 팁 및 모범 사례
성능을 위해 .length 캐시하기
int[] hugeArray = new int[1_000_000];
int length = hugeArray.length; // 한 번만 캐시
for (int i = 0; i < length; i++) {
// 루프 본문
}
캐시하면 빡빡한 루프에서 필드 접근을 반복하지 않아 성능이 향상됩니다.
배열 복사에 .length 활용
int[] source = {1, 2, 3, 4, 5};
int[] destination = new int[source.length]; // 동적 크기 지정
System.arraycopy(source, 0, destination, 0, source.length);
방어적 프로그래밍
public void processArray(int[] input) {
if (input == null || input.length == 0) {
// 엣지 케이스를 조기에 처리
return;
}
// 메인 로직
}
실제 사용 사례
사례 1: 이미지 처리
// 픽셀 데이터 처리 (단순화)
int[][] imagePixels = loadImage();
int height = imagePixels.length;
int width = imagePixels[0].length;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
imagePixels[y][x] = applyFilter(imagePixels[y][x]);
}
}
사례 2: 게임 개발
// 게임 엔티티 관리
Entity[] enemies = new Entity[MAX_ENEMIES];
int activeEnemies = 0;
public void updateGame() {
for (int i = 0; i < activeEnemies; i++) {
enemies[i].update();
}
}
사례 3: 데이터 배치 처리
// 데이터를 청크 단위로 처리
int[] allData = fetchDatabaseRecords();
int batchSize = 100;
for (int i = 0; i < allData.length; i += batchSize) {
int end = Math.min(i + batchSize, allData.length);
processBatch(allData, i, end);
}
배열(.length)만으로는 부족할 때
배열과 .length는 기본이지만, 실제 프로젝트에서는 동적 크기를 지원하는 ArrayList 같은 컬렉션을 더 많이 사용합니다. 그럼에도 배열을 이해하는 것이 중요한 이유는:
- 레거시 코드가 여전히 원시 배열을 사용한다.
- 컬렉션은 내부적으로 배열을 기반으로 구현된다.
- 성능이 중요한 구간에서는 여전히 배열을 사용한다.
자주 묻는 질문
Q: 배열을 만든 뒤에 .length를 바꿀 수 있나요?
A: 안 됩니다. 배열은 고정 크기이며, 동적 크기가 필요하면 ArrayList 같은 가변 컬렉션을 사용하세요.
Q: 배열 길이의 최대값은?
A: Integer.MAX_VALUE - 5 (≈ 21억) 정도이지만, 실제 한계는 메모리 제약에 따라 낮아집니다.
Q: .length는 0부터 시작하나요, 1부터 시작하나요?
A: 전체 용량을 반환합니다. 길이가 5인 배열이라면 유효 인덱스는 0‑4입니다.
Q: ArrayList.size()와 어떻게 다른가요?
A: .length는 배열의 고정 용량을 의미하고, size()는 가변 컬렉션에 현재 들어있는 요소 개수를 의미합니다.
Q: 빈 배열에서 .length는 어떻게 되나요?
int[] empty = new int[0];
System.out.println(empty.length); // 0 – 완전히 정상적인 값
결론
.length 필드를 이해하는 것은 Java 프로그래밍의 기본 중 하나입니다. 배열의 용량을 정확히 파악하게 해 주고, 흔히 발생하는 오류를 방지하며, 성능이 중요한 패턴에서도 핵심 역할을 합니다. 이를 마스터하면 배열은 물론, 그 위에 구축된 컬렉션까지도 자신 있게 다룰 수 있게 됩니다.