Java 에서는 클래스 안에 클래스가 들어갈 수 있다.

이를 Nested Class 라고 부르고 다음과 같이 분류할 수 있다.



* NestClass 를 만드는 이유 :

1) 코드를 간단하게 표현하기 위함

1-1) 소스의 가독성과 유지보수성을 높이고 싶을 때

2) Static Nested Class : 

- 한 곳에서만 사용되는 클래스를 논리적으로 묶어서 처리할 필요가 있을 때

3) Inner Class : 

- 캡슐화가 필요할 때 (ex. class A에 private 변수가 있다고 하자. 

이 변수에 접근하고 싶은 class B를 선언하고 B를 외부에 노출시키고 싶지 않을 경우가 이에 속한다) 



그런데 오해가 있을 수 있는데 아래의 코드를 보자. (PublicClass.java)

public class PublicClass {
}
class JustNotPublicClass {
}

1개의 자바 파일 안에 2개의 클래스가 선언되어도 문제될 건 없다.

하지만 JustNotPublicClass 는 단순히 Public Class 가 아닐 뿐이지, 이를 내부 클래스라고 할 수 없다.



* Static Nested Class :

Static 이기 때문에 외부 클래스 변수라고 다 참조하지 않는다. static 변수만 참조 가능.

길게 설명할 것 없이 어떻게 선언되는지 살펴보자.

public class OuterOfStatic { 
    static class StaticNested { 
        private int value = 0; 
        public int getValue() { 
            return value; 
        } 
    }
}

위의 클래스를 컴파일 하면 2개의 클래스가 만들어진다.

(OuterOfStatic.class, OuterOfStatic$StaticNested.class)


이렇게 선언해놓고 StaticNested 클래스 객체를 만들어 보겠다.

public static main(String[] args) { 
    OuterOfStatic.StaticNested staticNested = new OuterOfStatic.StaticNested(); 
    System.out.println(staticNested.getValue()); 
}

위와 같이 Static스럽게(?) 객체를 생성하면 된다.


왜 이렇게까지 하면서 만들어야 될까?

답변을 하자면, 클래스를 묶어서 가독성을 높이기 위해서이다.



* Inner Class :

여기서는 객체 생성 방법이 조금 다르다.

public class OuterOfInner { 
    class Inner { 
        private int value = 0; 
        public int getValue() { 
            return value; 
        } 
    }
}
public static main(String[] args) {
    OuterOfInner outer = new OuterOfInner();
    OuterOfInner.Inner inner = outer.new Inner();
    System.out.println(inner.getValue()); 
}


캡슐화를 위해 Inner Class 를 사용한다고 했었다.

A 클래스에서 어떤 공통적인 작업을 수행하는 B 클래스가 필요한데,

다른 클래스에서는 B 클래스가 전혀 필요가 없을 때는 이렇게 내부 클래스를 만들어 사용한다.


내부 클래스는 GUI 관련 프로그램을 개발할 때 가장 많이 사용된다고 한다.

(ex. EventListener)



다음은 익명 내부 클래스(Anonymous Inner Class)의 예제 코드이다.

public class NestedSample {
    public void setButtonListener() {
        Button btn = new Button();
        btn.setListener(new EventListener() {
            public void onClick() {
                System.out.println("Button was Clicked");
            }
        });
    } 
}

예제 코드라 코드가 조금 요상하지만_-_ 

어쨌든 주목할 부분은 Line 4 부터다. Java 로 GUI 코딩해보신 분들은 익숙할 법한 코드이다.


위와 같이 클래스의 이름도 없고, 객체의 이름도 없으면 외부에서 참조할 수가 없다. 


만약 재사용하고 싶다면

EventListener listener = new EventListener(){ // 생략 };

위와 같이 선언하면 된다. 또는 일반 내부 클래스처럼 만들어서 재사용해도 된다.



* 익명 클래스의 장점 :

클래스를 만들고 그 클래스를 호출하면 그 정보는 메모리에 올라간다.

즉, 클래스를 많이 만들면 만들수록 메모리는 많이 필요해지고 애플리케이션을 시작할 때 

더 많은 시간이 소요된다. 따라서 자바에서는 이렇게 익명으로 객체 생성이 가능하게끔 되어있다.


익명 클래스나 내부 클래스는 모두 다른 클래스에서 재사용할 일이 없을 때 만들어야 한다.

가독성을 높일 수 있다는 장점이 있지만 남용할 경우 가독성을 떨어뜨리기 때문에 주의하자.



* Nested Class 의 특징 :

- Static Nested 클래스는 외부 클래스의 static 변수만 참조할 수 있다.

- 그 외의 내부 클래스(Inner, Anonymous)는 외부 클래스의 어떤 변수라도 참조할 수 있다. (private도 가능!)

- 반대로 외부 클래스도 내부 클래스(Static, Inner, Anonymous)의 인스턴스 변수에 모두 접근할 수 있다.


위의 특징들은 꼭 기억하자.


by kelicia 2014. 5. 22. 18:03