🤔 Java에는 "길이"를 구하는 세 가지 방법
| 대상 | 길이 구하는 법 | 예시 |
| 배열 (int[]) | length (속성) | arr.length |
| 문자열 (String) | length() (메서드) | str.length() |
| 컬렉션 (List, Set, Map) | size() (메서드) | list.size() |
이렇게 서로 다르게 써야 한다는 것, 초보자 입장에선 헷갈립니다. 저도 처음엔 arr.length()를 쓰고 에러를 봤던 기억이 있습니다.
그런데 왜 이렇게 설계했을까? 왜 length() 하나로 통일하지 않았을까요?
🔍 자료형별로 왜 다르게 설계되었는가?
1. 배열: length는 속성 (field)
Java의 배열은 언어 차원에서 제공되는 primitive-level 구조입니다.
즉 클래스가 아니라, 같은 타입의 요소들을 연속된 메모리에 저장하는 객체입니다. int[], String[] 도 모두 객체이지만, JVM이 내부적으로 효율적으로 다룰 수 있도록 설계된 구조(=배열)입니다.
- 배열은 생성 시 크기가 고정되고, 요소의 수는 변경되지 않기 때문에
- 컴파일 타임에 length 필드로 직접 접근하는 것이 성능 면에서 유리합니다
int[] nums = {10, 20, 30};
System.out.println(nums.length); // 출력: 3
👉 length는 메서드가 아닌 public final 필드입니다. 괄호가 필요 없죠.
2. String: length()는 메서드
String은 클래스입니다. 내부에는 문자 데이터를 보관하는 배열이 들어있고, length() 메서드로 문자열 길이를 반환합니다.
- 불변(Immutable) 객체이고 캡슐화를 지키기 위해 직접 필드를 노출하지 않음
- 나중에 내부 구현을 바꿔도 외부 API를 유지할 수 있음
String 클래스 length() 구조입니다. Java 9부터는 성능 개선을 위해 내부에 char[] 대신 byte[]가 사용됩니다.
- value는 내부 byte[] 배열입니다
- coder()는 Latin-1(1바이트) 또는 UTF-16(2바이트) 여부를 판별합니다
- 결과적으로 length()는 문자 개수를 반환하기 위한 로직이 들어간 메서드입니다
// String class length()
public int length() {
/*
* coder(): 현재 문자열이 Latin-1(1)인지, UTF-16(2)인지 구분하기 위해 사용
* coder() == 0 → value.length >> 0 = 그대로 → Latin-1 (1바이트당 1글자)
* coder() == 1 → value.length >> 1 = 2바이트당 1글자 → UTF-16
*/
return value.length >> coder();
}
👉 단순한 필드 접근이 아니라, 내부 구조와 인코딩을 고려해야 하므로 메서드로 제공되는 것이 타당합니다.
3. 컬렉션: size() 메서드
List, Set, Map 등은 다양한 구현체를 갖는 인터페이스 기반 구조입니다. 크기를 구하는 방식도 다양할 수 있기에, 인터페이스에서 일관된 이름의 메서드(size())로 제공됩니다:
- 구조가 다르기 때문에 length 같은 속성으로 추상화가 불가능
List<String> list = new ArrayList<>();
list.add("Java");
list.add("GPT");
System.out.println(list.size()); // 출력: 2
👉 다형성과 일관성을 위해 size()라는 공통 메서드로 제공
🧠 자바 설계 관점에서 본 이유 정리
성능, 구조, 일관성 사이의 균형을 고려한 결과
| 자료형 | 길이 접근 방식 | 이유 |
| 배열 | length 필드 | 고정 크기, 빠른 접근 |
| 문자열 | length() 메서드 | String은 객체 → 캡슐화, 추상화 / 내부 로직 포함 (byte[], 인코딩 등) |
| 컬렉션 | size() 메서드 | 다양한 구조를 위한 공통 인터페이스 |
💬 추가 : 통일 안 하고 그대로 둔 이유
- Java는 후방 호환성 (backward compatibility) 을 매우 중요시함
- length, length(), size()는 초기부터 구분되어 사용되어 왔고, 이를 바꾸면 수많은 코드가 깨짐
- 각 타입별로 "가장 적절한 방식"을 선택했기 때문에, 일관성보다 안정성과 효율을 택한 것
📚 참고 자료
- [Oracle Java Tutorials – Arrays] (https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html)
- [Java API: String.length()] (https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/String.html#length())
- [Java API: List.size()] (https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/List.html#size())
- [JLS §10.7 Array Members] (https://docs.oracle.com/javase/specs/jls/se21/html/jls-10.html#jls-10.7)
'Code Odyssey' 카테고리의 다른 글
| Kotlin 코딩테스트 문법 시리즈 ② : 문자열 (String) (1) | 2025.07.02 |
|---|---|
| Kotlin 코딩테스트 문법 시리즈 ① : 기본 자료형 & 변수 (0) | 2025.07.01 |
| Map<String, Integer> dp 는 시간초과가 나는 이유 : 프로그래머스 - 사칙연산 (1) | 2025.06.11 |
| 📌 Java에서 배열 정렬하기 - Arrays.sort() (0) | 2025.05.24 |
| Arrays 유용 메서드 정리 (0) | 2025.04.26 |