중첩 클래스란 다른 클래스 내부에 정의된 클래스를 말한다.
- 두 클래스의 멤버들을 쉽게 접근 가능
- 외부로부터 불필요한 관계 클래스를 감춤으로써 코드의 복잡성 감소
- static으로 선언한 멤버 클래스를 static 중첩 클래스라고 부른다.
- 정적 멤버 클래스
- non-static 멤버 클래스를 내부 클래스라고 부른다.
- 비정적 멤버 클래스
- 익명 클래스
- 지역 클래스
정적 멤버 클래스는 바깥 클래스 내부에 static으로 선언된 클래스이다.
- 바깥 클래스의
private
멤버에도 접근 가능 - 흔히 바깥 클래스와 함께 쓰일 때만 유용한 public 도우미 클래스로 쓰인다.
public class Person {
private final String name;
private final int age;
private final int weight;
private final int height;
public static class Builder {
private final String name;
private final int age;
private int weight = 0;
private int height = 0;
public Builder(String name, int age) {
this.name = name;
this.age = age;
}
public Builder weight(int val) {weight = val; return this;}
public Builder height(int val) {height = val; return this;}
public Person build() {
return new Person(this);
}
}
private Person(Builder builder) {
name = builder.name;
age = builder.age;
weight = builder.weight;
height = builder.height;
}
}
Person JJANG9 = new Person.Builder("짱구", 7)
.weight(80).height(200).build();
비정적 멤버 클래스란 바깥 클래스 내부에 static 키워드 없이 선언된 클래스이다.
- 바깥 인스턴스 없이는 존재할 수 없다.
- 인스턴스 메서드에서 정규화된 this를 사용해 바깥 인스턴스의 메서드를 호출한다거나 바깥 인스턴스를 참조할 수 있다.
public class Outer {
String name = "짱구";
public void run() {
Inner inner = new Inner();
inner.run();
}
public class Inner {
public void run() {
System.out.println(Outer.this.name);
}
}
}
멤버 클래스에서 바깥 인스턴스에 접근할 일이 없다면 무조건 static을 붙여서 정적 멤버 클래스로 만들자.
- static을 생략하면 바깥 인스턴스로의 숨은 외부 참조를 갖게 되고 심각한 경우 GC가 바깥 인스턴스를 수거하지 못하는 경우가 발생한다. (메모리 누수)
익명 클래스는 사용 시점에 인스턴스화 되어 한번만 사용할 수 있게 만든 클래스이다.
익명이라 이름이 없기 때문에 생성자를 가질 수 없고 단 하나의 클래스를 상속받거나 하나의 인터페이스만 구현 가능하다.
- 익명 클래스에 새롭게 정의된 필드와 메서드는 익명 클래스 내부에서만 사용 가능하다.
- 람다가 나오면서 익명 클래스는 빠이~
public class Anonymous {
public void show() {
}
}
public class Main {
public static void main(String[] args) {
Anonymous anonymous = new Anonymous() {
public void hide() {
System.out.println("는 못말려!");
}
@Override
public void show() {
System.out.print("짱구");
hide();
}
};
//anonymous.hide(); 호출 불가
anonymous.show();
}
}
지역 클래스는 가장 드물게 사용되는 중첩 클래스이다.
- 접근 제한자(public, private) 및 static을 붙일 수 없다.
- 메서드 내부에서만 사용되기 때문에 접근을 제한할 필요가 없다.
- 정적 멤버(정적 필드와 메서드)를 가질 수 없다.
public class OuterJJANG9 {
private String outerMessage = "짱";
public void method() {
class LocalJJANG9 {
public void print() {
String localMessage = "구";
System.out.println(outerMessage + localMessage);
}
}
LocalJJANG9 localJJANG9 = new LocalJJANG9();
localJJANG9.print();
}
}