Java Nested - 정적 중첩 클래스

정적 중첩 클래스를 사용한 예제 코드이다.

public class NestedOuter {
    private static int outClassValue = 3;
    private int outInstanceValue =2;

    // 정적 중첩 클래스
    static class Nested {
        private int nestedInstanceValue = 1;

        public void print() {
            // 자신의 멤버로 접근
            System.out.println(nestedInstanceValue);

            // 바깥 클래스의 인스턴스 멤버 접근 -> 접근 불가능
            // 이 정적 중첩 클래스는 인스턴스와 상관 없다. 당연 outInstanceValue 모른다.
            // System.out.println(outInstanceValue);

            // 바깥 클래스의 클래스 멤버에는 접근 할 수 있음
            System.out.println(NestedOuter.outClassValue);
        }
    }
}

멤버 변수는 다음과 같이 선언되어 있다.

NestedOuter의 멤버 변수

  • outClassValue
    • 접근제어자는 private 그리고 static 키워드로 정적이다.
  • outInstanceValue
    • 접근제어자는 private 그리고 static 키워드가 없다.
  • nestedInstanceValue
    • 정적 중첩 클래스 내부에 있는 변수이다.

다음으로 정적 중첩 클래스 내부로 각각의 멤버변수를 호출하면 어떻게 되는지 살펴보자.

NestedOuter.Nested 정적 중첩 클래스에서의 멤버변수 호출

  • nestedInstanceValue
    • 같은 클래스 내부로 있으므로 호출이 가능하다.
  • outInstanceValue
    • 먼저 outInstanceValue 인스턴스 변수이다. Nested 클래스 입장에서는 static 클래스로써 인스턴스 변수는 알지 못한다.
  • outClassValue
    • 이 변수는 static 변수이다. private 접근 제어는 Nested 클래스가 NestedOuter 내부에 있으므로 접근할 수 있고 NestedOuter.outClassValue 호출하여 사용할 수 있다.

private 접근제어자

앞서 예제 코드에서 private 사용한 모습을 볼 수 있었다. 이로 인해 알 수 있는점은 다음과 같다.

  • private 접근 제어자는 같은 클래스 안에서만 접근할 수 있다.
  • 중첩 클래스 또한 바깥 클래스 내부에 있는 클래스이다. 따라서 private 접근제어자로 접근 한다.

외부 호출

예제 코드 이어서 외부 Main.class 에서 정적 중첩 클래스를 호출하는 코드를 살펴보자

Main.class

public class Main {
    public static void main(String[] args) throws Exception {
        NestedOuter outer = new NestedOuter();
        NestedOuter.Nested nested = new NestedOuter.Nested();

        nested.print();
    }
}

1
3

getClass()

System.out.println(nested.getClass());

class NestedOuter$Nested

getClass 에서는 중첩 클래스를 $ 인자로 구분해서 표시해주고 있다.

바깥 클래스에서의 중첩 클래스 호출

NestedOuter outer = new NestedOuter();

System.out.println(outer.Nested.print()); // 접근 불가
System.out.println(outer.Nested.nestedInstanceValue); // 접근 불가

java: unexpected type

인스턴스를 바깥클래스로 생성하고 정적 중첩 클래스의 멤버 변수와 멤버 메소드를 호출했으나 실패한다.

정리

  • 정적 중첩 클래스는 new 바깥클래스.중첩클래스() 객체 생성
  • 중첩 클래스는 NestedOuter.Nested 와 같은 바깥클래스.중첩클래스 형태로 접근
  • 바깥 클래스와 정적 중첩 클래스의 인스턴스끼리는 아무런 관계가 아니다.
    • new NestedOuter() != new NestedOuter.Nested()
    • 정적 중첩 클래스 인스턴스 생성을 NestedOuter.Nested() 따로 생성