HOWTO · Java
Java의 정적 클래스
이 기사에서는 Java 정적 클래스를 소개합니다.
이 페이지의 내용
Java에서는 최상위 클래스를 static으로 선언할 수 없습니다. 다른 클래스 안에 선언된 클래스는 static으로 선언할 수 있으며, 이를 정적 중첩 클래스라고 합니다. 정적 중첩 클래스는 바깥 클래스의 인스턴스 없이 생성할 수 있고, 바깥 클래스의 정적 멤버를 사용할 수 있습니다. 호출자가 공개 API를 통해 생성할 수 없는 유틸리티 클래스를 원한다면 대신 private 생성자를 사용하세요. 이는 별도의 설계 패턴입니다.
Java의 정적 중첩 클래스란?
정적 중첩 클래스는 다른 클래스 내부에 static 키워드와 함께 선언하는 멤버 타입입니다. static 한정자는 중첩 클래스의 인스턴스가 바깥 클래스 객체를 암묵적으로 참조하지 않는다는 뜻입니다. 정적 중첩 클래스 자체를 생성할 수 없다는 뜻은 아닙니다. Container.Entry와 같이 바깥 타입을 통해 타입에 접근하며, 인스턴스 메서드는 해당 중첩 타입의 인스턴스에서 호출합니다.
정적 중첩 클래스는 private 멤버를 포함해 바깥 클래스의 정적 멤버에 접근할 수 있습니다. 바깥 클래스의 인스턴스가 있는 것처럼 그 필드나 메서드를 참조할 수는 없습니다. 다만 바깥 클래스 객체를 명시적으로 전달하면 해당 멤버를 사용할 수 있습니다.
정적 중첩 클래스 선언 및 사용 방법
멤버 클래스를 static으로 선언한 다음, 바깥 타입의 이름을 사용해 인스턴스를 생성합니다. 다음 전체 예제에서는 바깥 클래스의 정적 필드에 접근하는 방법도 보여 줍니다.
이 예제를 실행하세요.
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.
public class Container {
private static int count = 3;
public static class Entry {
public int value() {
return count;
}
}
public static void main(String[] args) {
Container.Entry entry = new Container.Entry();
System.out.println(entry.value());
}
}
3
예제를 실행하면 3이 출력됩니다. 예제를 수정할 때는 중첩 클래스를 바깥 클래스 내부에 두고, Container 바깥에서 타입을 사용할 때는 Container.Entry로 지정하세요. Entry 객체는 일반 인스턴스이고, count는 바깥 클래스 자체에 속합니다.
정적 중첩 클래스와 내부 클래스 비교
비정적 멤버 클래스는 흔히 내부 클래스라고 합니다. 내부 클래스를 생성하려면 바깥 클래스의 인스턴스가 필요합니다. Container 객체를 만든 다음 container.new Inner()를 사용합니다. 내부 클래스 인스턴스는 바깥 객체와의 연결을 유지하므로 바깥 객체의 인스턴스 멤버를 직접 사용할 수 있습니다.
정적 중첩 클래스에는 이러한 암묵적인 연결이 없습니다. 바깥 클래스의 인스턴스 필드를 읽으려면 Container 객체를 전달하거나 다른 방법으로 얻은 뒤, 해당 참조를 통해 필드에 접근해야 합니다. 두 종류의 중첩 클래스 모두 Java의 중첩 타입 접근 규칙에서 허용하는 멤버에 접근할 수 있습니다. 핵심 차이는 바깥 클래스 인스턴스를 자동으로 사용할 수 있는지 여부입니다.
인스턴스화할 수 없는 유틸리티 클래스 만들기
유틸리티 클래스는 객체마다 상태를 가질 필요가 없는 작업이나 상수를 한데 모읍니다. 일반 최상위 클래스에 해당 멤버를 선언하고, 적절한 멤버를 static으로 지정한 다음 private 생성자를 추가하면 일반 호출자가 클래스 외부에서 new를 호출할 수 없습니다. 예를 들어 다음 패턴을 사용할 수 있습니다. public final class TextTools { private TextTools() {} public static String join(String first, String second) { return first + second; } }. 호출은 TextTools.join("static ", "utility")와 같이 합니다.
private 생성자는 일반적인 외부 생성을 막지만, TextTools를 정적 클래스로 바꾸지는 않습니다. Java에는 최상위 정적 클래스가 없습니다. 클래스를 final로 선언하는 것은 선택 사항이며 상속만 제한합니다. 유틸리티 메서드의 필수 조건이 아니라, 상속 제한이 설계의 일부일 때 사용하세요.
정적 클래스에 관한 흔한 오해
정적 중첩 클래스는 인스턴스화할 수 있습니다. static은 바깥 클래스 인스턴스를 암묵적으로 요구하지 않게 합니다. 정적 중첩 클래스의 인스턴스 메서드는 그 클래스 자체의 인스턴스 필드를 사용할 수 있습니다. 바깥 클래스 이름으로 중첩 타입을 지정하더라도, 인스턴스 메서드를 호출하려면 중첩 타입의 객체가 필요합니다.
정적 문맥에서는 바깥 객체를 자동으로 사용할 수 없으므로, 바깥 클래스의 인스턴스 멤버를 한정되지 않은 이름으로 접근할 수 없습니다. 명시적인 객체 참조를 통해서는 접근할 수 있습니다. 마찬가지로 private 유틸리티 생성자는 클래스 외부에서의 일반적인 호출을 막는 것이지, 어떤 상황에서도 객체 생성이 불가능하게 만드는 것은 아닙니다. 이러한 차이를 이해하면 Java의 중첩 클래스 문법과 유틸리티 클래스 패턴을 구분할 수 있습니다.