본문 바로가기
카테고리 없음

[Java] str.length()와 arr.length의 차이점: 왜 하나는 메서드고 하나는 속성일까?

by 프로P 2026. 6. 8.

자바를 다루다 보면 누구나 한 번쯤 "대체 왜 어떤 건 뒤에 괄호가 붙고, 어떤 건 안 붙지?" 하며 헷갈리는 순간이 찾아옵니다.

String str = "Hello";
int[] arr = {1, 2, 3};

int len1 = str.length(); // 괄호가 있음 (메서드)
int len2 = arr.length;   // 괄호가 없음 (속성/필드)

 

모양은 비슷한데 하나는 메서드(()) 호출이고, 하나는 참조 변수의 속성(field) 접근입니다. 왜 자바 설계자들은 이 둘을 다르게 만들었을까요? 자바의 내부 구조와 객체지향 설계 관점에서 그 이유를 파헤쳐 보겠습니다.

1. arr.length : 배열은 JVM이 관리하는 '특수한 객체'다

자바에서 배열(Array)은 일반적인 클래스로 정의된 객체가 아니라, 언어 자체(JVM)에서 레벨에서 관리하는 빌트인(Built-in) 특수 객체입니다.

배열은 선언 및 생성 시점에 메모리 크기가 고정되며, 이후로는 절대 변하지 않는다는 특징을 가집니다. 자바 설계자들은 이 고정된 크기 값을 외부에서 변경하지 못하도록 final로 제약을 걸되, 개발자가 가장 빠르게 읽어올 수 있도록 최적화하고자 했습니다.

따라서 별도의 메서드 호출 오버헤드(Call Stack 생성 등) 없이, 메모리에 로드된 배열 객체의 상수 필드에 곧바로 접근할 수 있도록 public final int length라는 속성(Field)으로 노출해 둔 것입니다.

2. str.length() : String은 철저히 캡슐화된 '표준 클래스'다

반면 String은 자바 표준 라이브러리(java.lang.String)에 엄연히 정의되어 있는 일반적인 클래스입니다.

자바 객체지향 프로그래밍(OOP)의 핵심 원칙 중 하나는 캡슐화(Encapsulation)입니다. 즉, 클래스 내부의 실제 데이터(필드)는 private으로 꽁꽁 숨기고, 외부에 노출할 때는 정제된 메서드(Method)를 통해서만 접근할 수 있도록 제한하는 것이죠.

실제로 자바의 String 내부 소스코드를 뜯어보면, 문자열 데이터를 저장하는 배열을 다음과 같이 감추고 있습니다.

public final class String {
    /** The value is used for character storage. */
    private final byte[] value; // 내부 데이터 배열은 private으로 은닉됨

    // 외부에 데이터 길이를 제공할 때는 메서드를 통함
    public int length() {
        return value.length; // 결국 내부 private 배열의 .length 속성을 대리 반환
    }
}

우리가 str.length()를 호출하면, String 객체는 내부적으로 자신이 숨겨두고 있던 실제 데이터 배열의 .length 속성을 꺼내서 리턴해 줍니다. 내부 구현은 철저히 숨긴 채 호환성과 안전성을 지키겠다는 객체지향 설계 규칙을 정석대로 따른 결과인 셈입니다.

덤으로 묶어 외우기 (Collection) 이후에 자주 쓰게 될 ArrayList나 HashSet 같은 컬렉션 프레임워크들은 인터페이스 규격을 따르는 완벽한 객체들이기 때문에 크기를 가져올 때 .size() 메서드를 사용합니다

마치며

별생각 없이 쓰던 괄호 두 개(())의 차이 속에는 자바가 배열을 다루는 하드웨어적인 최적화 방식과, 클래스를 다루는 소프트웨어적인 객체지향 철학이 동시에 녹아 있었습니다.

이러한 언어적 비하인드를 이해하고 코드를 작성하면 혼동을 줄일 수 있을 뿐만 아니라, 컴파일러 너머의 메모리 구조를 조금 더 입체적으로 바라볼 수 있게 됩니다.