관리 메뉴

제뉴어리의 모든것

내부 클래스 개념 본문

JAVA

내부 클래스 개념

제뉴어리맨 2022. 8. 24. 16:55

내부 클래스란?

말 그대로 Class 내부에 존재하는 Class이다.

 

내부 클래스 예

class OuterClass{

    class NonStaticInnerClass{ //스태틱이 아닌 내부 클래스
        int value;

        public NonStaticInnerClass(int value) {
            this.value = value;
        }

        @Override
        public String toString() {
            return "NonStaticInnerClass{" +
                    "value=" + value +
                    '}';
        }
    }

    static class StaticInnerClass{ //스태틱인 내부 클래스
        int value;

        public StaticInnerClass(int value) {
            this.value = value;
        }

        @Override
        public String toString() {
            return "NonStaticInnerClass{" +
                    "value=" + value +
                    '}';
        }
    }
}

위 처럼 OuterClass 라는 클래스는 내부에

NonStaticInnerClass

StaticInnerClass

라는 두가지의 내부 클래스를 가진다.

그런데 코드를 보면 알 수 있듯이,

NonStaticInnerClass 는 static 키워드가 붙지 않은 일반 클래스이고,

StaticInnerClass 는 static 키워드가 붙은 정적 클래스이다.

 

static 키워드의 의미

우리가 주로 static을 사용하는 경우는

class 내부에 특정 멤버 변수나 멤버 메소드에 static을 붙여서 해당 class가 static이 붙은 멤버 변수를 공유하거나,

해당 클래스의 객체 생성 없이 메소드를 호출할때 static 이 사용된다.

 

그렇다면, 클래스에 static이 붙으면 어떤 의미일까?

 

우선 명심해야할것이 있다.

클래스 내부에 클래스라는 것은 결국 해당 클래스에 속한것이라는것이다.

그리고 특정 클래스에 속해 있는것을 접근할때 우리는 어떻게 하는가?

 

ClassA classA = new ClassA();

classA.value = 1; // ClassA에 value라는 int형 타입 변수가 선언되어 있다고 가정하자.

 

위와 같이 객체를 생성 한뒤, 해당 객체에 .을 찍어 참조하겠다는 표현을 한 뒤, 변수에 접근한다 (메소드 또한 동일)

클래스 또한 동일한다.

 

위에 OuterClass 를 사용하여 예시를 보겠다.

public class test {
    @Test
    void method(){

        OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass(1);
        OuterClass.NonStaticInnerClass nonStaticInnerClass = new OuterClass.NonStaticInnerClass(1);
    }

}

위와 같이 OuterClass에 .을 찍어 참조하겠다는 표현을 한뒤 내부클래스를 생성 가능하다.

그러나, 

OuterClass.NonStaticInnerClass nonStaticInnerClass = new OuterClass.NonStaticInnerClass(1); 부분은 에러가 날것이다.

왜냐하면, 

클래스 내부에 존재하는것에 접근을 하려면, 우선 해당 클래스의 객체를 생성한 뒤,

.을 찍어 객체를 참조하여 접근이 가능하기 때문이다.

 

(OuterClass.NonStaticInnerClass nonStaticInnerClass = new OuterClass().new NonStaticInnerClass(1) 로 하면 되긴 한다 그러나 결국 OuterClass의 객체를 생성해야한다)

 

그런데, 위에 method() 메소드를 보면 OuterClass는 객체가 생성되지 않았다.

그러므로 객체 내부에 존재하는 변수나, 메소드는 물론 클래스에도 접근을 할 수 없는것이다. (static 변수, 메소드, 클래스가 아니기 때문이다)

그래서 내부 클래스의 객체를 외부 클래스 생성 없이 사용하고 싶다면 static 키워드를 붙여주어야한다.

 

그래서 결국

 

클래스 내부의 것 (변수, 메소드, 클래스) 을 사용하려면 -> 

1. 클래스의 객체를 생성한다.

2. 생성된 객체를 참조한다.

 

이란 공식이 존재한다.

 

그런데 의문이 들것이다.

멤버 변수에 static을 붙이면 해당 클래스의 모든 객체들이 해당 멤버 변수의 값을 공유한다.

 

첫번째 의문, 그렇다면 static 내부 클래스는 모든 외부 클래스의 객체들에게 공유되는것일까?

두번째 의문, 아니면 객체를 아무리 많이 만들어도 최종 하나의 객체만 생성되는것일까?

아니면 다른 뭔가가 있는것일까?

 

우선 Outer 클래스를 생성하여 보자.

       OuterClass outerClass = new OuterClass();
        outerClass.StaticInnerClass = new OuterClass.StaticInnerClass(); //해당 코드 에러

우선 outerClass 인스턴스에서 StaticInnerClass에 접근 하는거 자체가 불가능하다.

그러므로 첫번째 의문의 상황은 애초에 존재 할 수가 없다.

 

(그런데 여기서 의문,,,

static이 아닌 인스턴스에서 static 인 멤머 변수나 멤버 변수의 접근은 왜 안될까?

어차피 인스턴스의 생성전이나 후나 항상 존재할 static 멤버, static 클래스들인데 말이다..

추후 깊이 알아보자...

)

 

 

 

그렇다면 두번째 의문상황을 확인해보자.

과연 static으로 선언 클래스는 독립된 여러개의 객체 생성이 가능할까

코드를 아래와 같이 테스트 해보자.

public class test {
    @Test
    void method(){

        OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass(1);
//        OuterClass.NonStaticInnerClass nonStaticInnerClass = new OuterClass.NonStaticInnerClass(1);

        OuterClass.StaticInnerClass[] arr = new OuterClass.StaticInnerClass[3];
        arr[0] = new OuterClass.StaticInnerClass(1);
        arr[1] = new OuterClass.StaticInnerClass(10);
        arr[2] = new OuterClass.StaticInnerClass(100);

        for (OuterClass.StaticInnerClass innerClass : arr) {
            System.out.println(innerClass);
        }
    }
}

 

아래는 결과 화면이다.

일반 클래스처럼 잘 생성되며, static 멤버 필드처럼 공유되는 현상도 없다.

 

왜냐하면 클래스내의 멤버변수는 뭔가가 저장되는 메모리 공간을 할당받는 개념이지만,

클래스 내의 클래스는 메모리 공간을 할당 받는 개념이 아니라,

그냥 클래스의 명세영역인것이다.

 

 

결론

내부 클래스에 static을 붙이는 이유는

외부 클래스의 객체 생성 없이 사용하려고 하는것이다.

그리고 static class는 일반 클래스와 같이 똑같이 객체를 생성하여 사용할 수 있다.

 

참조 내용 : https://stackoverflow.com/questions/20252727/is-not-an-enclosing-class-java

 

 

추가적인 내용

외부 클래스에 static 키워드는 왜 안되는것일까?

위와 같이 OuterClass에 static 키워드는 불가능하다.

왜냐하면,

내부 클래스가 아닌 외부 클래스는 이미 정적이기 때문이다.

이미 해당 클래스는 명세는 static 영역에 올라갈것이기 때문이다.

그러므로, 불가능하다기 보다는 의미가 없기에 static 키워드를 사용할 수 없는것이다.

참조 내용 : https://stackoverflow.com/questions/18036458/why-cant-we-have-static-outer-classes