class Outer {
class Nested { ... } // 네스티드 클래스
}
클래스 내에 정의된 클래스를 네스티드 클래스(Nested Class)라고 하고, 이를 감싸는 클래스를 외부 클래스(Outer Class)라고 한다.
네스티드 클래스는 static 선언 여부를 기준으로 Static 네스티드 클래스와 Non-static 네스티드 클래스로 나뉜다.
Static 네스티드 클래스(Static Nested Class)
class Outer {
private static int num = 0;
static class Nested1 {
void add(int n) { num += n; }
}
static class Nested2 {
int get() { return num; }
}
}
Outer.Nested1 nst1 = new Outer.Nested1();
nst1.add(5);
Outer.Nested1 nst2 = new Outer.Nested2();
System.out.println(nst2.get()); // 5
외부 클래스 인스턴스와 상관없이 Static 네스티드 클래스의 인스턴스 생성이 가능하다.
Static 네스티드 클래스 내에서는 외부 클래스에 static 으로 선언된 변수와 메서드에만 접근 가능하다. 위의 코드를 보면 static으로 선언된 num을 모든 인스턴스가 공유하고 있다.
이너 클래스(Inner Class)
Non-static 네스티드 클래스를 이너 클래스(Inner Class)라고 하는데, 이너 클래스는 정의되는 위치나 특성에 따라 세종류로 나뉜다.
- 멤버 이너 클래스(Member Inner Class)
- 로컬 이너 클래스(Local Inner Class)
- 익명 이너 클래스(Anonymous Inner Class)
일반적으로 이너를 생략하고 멤버 클래스, 로컬 클래스, 익명 클래스로 부른다.
멤버 클래스(Member Class)
class Outer {
private int num = 0;
class Member { ... }
}
Outer o1 = new Outer();
Outer.Member o1m1 = o1.new Member();
Outer.Member o1m2 = o1.new Member();
o1m1.add(5);
System.out.println(o1m2.get()); // 5
인스턴스 변수, 인스턴스 메서드와 동일한 위치에 정의되어 있는 클래스이다.
멤버 클래스의 인스턴스는 외부 클래스의 인스턴스에 종속적이다. 위의 코드에서 볼 수 있듯이 Outer 인스턴스 없이 Member 인스턴스 생성이 불가능하다. 또한, o1m1과 o1m2는 o1이 참조하는 인스턴스의 멤버에 접근할 수 있으며 인스턴스의 멤버를 공유한다.
멤버 클래스는 클래스의 정의를 감추어야 할 때 유용하게 쓰인다.
interface Printable {
void print();
}
class Papers {
...
public Printable getPrinter() {
return new Printer();
}
private class Printer implements Printable {
public void print(){
System.out.println(str);
}
}
}
Papers paper = new Papers("종이맨");
Printable prn = paper.getPrinter();
prn.print();
멤버 클래스가 private로 선언되면, 이 클래스의 정의를 감싸는 클래스 내에서만 생성이 가능하다. Papers 클래스 외부에서는 getPrint 메서드가 어떤 인스턴스의 참조값을 반환하는지 알지 못하는데 이러한 상황을 클래스의 정의가 감추어진 상황이라고 한다. 클래스의 정의를 감추면 getPrinter 메서드의 반환 인스턴스가 변경되어도 Papers 클래스 외부 코드는 수정할 필요가 없어 코드에 유연성이 생긴다. 컬렉션 프레임워크의 반복자(Iterator)가 멤버 클래스의 형태로 정의되어 있다.
List<String> list = new ArrayList<>();
Iterator<String> itr = list.iterator();
로컬 클래스(Local Class)
중괄호 내에, 특히 메서드 내에 정의된 클래스이다. 멤버 클래스와 상당 부분 유사하지만 정의되는 위치가 다르다.
interface Printable {
void print();
}
class Papers {
...
public Printable getPrinter() {
class Printer implements Printable {
public void print(){
System.out.println(str);
}
}
return new Printer();
}
}
Papers paper = new Papers("종이맨");
Printable prn = paper.getPrinter();
prn.print();
메서드 내에서 클래스를 정의하면 매서드 내에서만 인스턴스 생성이 가능하므로, 멤버 클래스보다 클래스를 더 깊이 감추는 효과가 이싿.
익명 클래스(Anonymous Class)
클래스의 이름이 존재하지 않는 클래스이다. 클래스의 정의와 인스턴스의 생성이 한번에 수행된다.
interface Printable {
void print();
}
class Papers {
...
public Printable getPrinter() {
return new Prinatable() {
public void print(){
System.out.println(str);
}
};
}
}
Papers paper = new Papers("종이맨");
Printable prn = paper.getPrinter();
prn.print();
참조
윤성우의 열혈 JAVA 프로그래밍
댓글