정적 멤버 클래스
• 바깥 클래스와 함께 쓰일 때만 유용한 public 도우미 클래스. 예) Calculator.Operation.PLUS
InnerClassd 밖의 static field 에 접근이 가능하다.
public class OutterClass {
private static int number = 10;
static private class InnerClass {
void doSomething() {
System.out.println(number);
}
}
public static void main(String[] args) {
InnerClass innerClass = new InnerClass();
innerClass.doSomething();
}
}
비정적 멤버 클래스
• 바깥 클래스의 인스턴스와 암묵적으로 연결된다.
• 어댑터를 정의할 때 자주 쓰인다.
• 멤버 클래스에서 바깥 인스턴스를 참조할 필요가 없다면 무조건 정적 멤버 클래스로 만들자.
public class OutterClass {
private int number = 10;
void printNumber() {
InnerClass innerClass = new InnerClass();
}
private class InnerClass {
void doSomething() {
System.out.println(number);
OutterClass.this.printNumber();
}
}
public static void main(String[] args) {
**InnerClass innerClass = new OutterClass().new InnerClass();**
innerClass.doSomething();
}
}
익명 클래스
• 바깥 클래스의 멤버가 아니며, 쓰이는 시점과 동시에 인스턴스가 만들어진다.
• 비정적인 문맥에서 사용될 때만 바깥 클래스의 인스턴스를 참조할 수 있다.
• 자바에서 람다를 지원하기 전에 즉석에서 작은 함수 객체나 처리 객체를 만들 때 사용했다.
• 정적 팩터리 메서드를 만들 때 사용할 수도 있다.
public class IntArrays {
static List<Integer> intArrayAsList(int[] a) {
Objects.requireNonNull(a);
// 다이아몬드 연산자를 이렇게 사용하는 건 자바 9부터 가능하다.
// 더 낮은 버전을 사용한다면 <Integer>로 수정하자.
return new AbstractList<>() {
@Override public Integer get(int i) {
return a[i]; // 오토박싱(아이템 6)
}
@Override public Integer set(int i, Integer val) {
int oldVal = a[i];
a[i] = val; // 오토언박싱
return oldVal; // 오토박싱
}
@Override public int size() {
return a.length;
}
};
}
public static void main(String[] args) {
int[] a = new int[10];
for (int i = 0; i < a.length; i++)
a[i] = i;
List<Integer> list = intArrayAsList(a);
Collections.shuffle(list);
System.out.println(list);
}
}
지역 클래스
• 가장 드물게 사용된다.
• 지역 변수를 선언하는 곳이면 어디든 지역 클래스를 정의해 사용할 수 있다.
• 가독성을 위해 짧게 작성해야 한다