정적 멤버 클래스
다른 클래스 안에 선언되고, 바깥 클래스의 private 멤버에 접근할 수 있다는 점만 빼면 일반 클래스가 다르지 않다.
바깥 클래스와 함께 쓰일 때만 유용한 public 헬퍼 클래스로 쓰인다.
정적 멤버 클래스 예시
비정적 멤버 클래스
구문상으로는 정적 멤버 클래스에서 static만 빠졌지만, 의미상으로 차이가 크다.
바깥 클래스의 인스턴스와 연결된다.
비정적 멤버 클래스의 인스턴스 메소드에서 정규화된 this를 사용해 바깥 인스턴스의 메소드를 호출하거나 바깥 인스턴스의 참조를 가져올 수 있다.
정규화된 this란?
비정적 멤버 클래스 예시 - 1 (책의 예제)
비정적 멤버 클래스 예시 - 2 (현실 사용)
멤버 클래스에서 바깥 인스턴스에 접근할 일이 없다면 무조건 static을 붙여서 정적 멤버 클래스로 만들자.
static을 생략하게 되면 숨은 외부 참조를 불필요하게 갖게되어, 이 참조를 저장하기 위한 시간과 공간이 낭비된다.
심지어 가비지 컬렉터가 수거해가지 못하여 메모리 누수가 발생할 수 있다.
익명 클래스
익명 클래스는 이름이 없는 클래스이다. (그것이 익명이니까..!)
익명 클래스란?
얘는 바깥 클래스의 멤버도 아니다. 멤버와는 달리 쓰이는 시점에 선언과 동시에 인스턴스가 생성된다.
람다를 사용하기 전에는 즉석에서 빠르게 작은 함수 객체나 처리 객체를 만들기 위해 사용했으나, 지금은 정적 팩터리 메소드를 구현할 때 정도로만 사용되는 듯 하다.
익명 클래스 사용 예시
지역 클래스
가장 안쓰인다.
지역 클래스는 지역변수를 선언할 수 있는 곳이라면 어디서든 선언할 수 있고, scope도 지역변수와 같다.
멤버 클래스처럼 이름이 있고 반복해서 사용가능하다.
익명 클래스처럼 비정적 문맥에서 사용될 때만 바깥 인스턴스를 참조할 수 있다.
정적 멤버를 가질 수 없고, 가독성을 위해 짧게 작성해야 한다.
지역 클래스 사용 예시
익명 클래스처럼 한 메소드 안에서만 쓰이면서 인스턴스를 한 곳에서만 쓰일 때 사용하지만, 위에서 Animal 예시처럼 리스코프 교체가 원할하게 이루어질 수 있는 상황이라면 익명 클래스를 이용하고, 그렇지 않으면 지역 클래스로 활용하는 것이 좋다고 이해했다.
저자의 핵심 정리
증첩 클래스에는 네 가지가 있으며, 각각의 쓰임이 다르다.
메서드 밖에서도 사용해야 하거나 메서드 안에 정의하기엔 너무 길다면 멤버 클래스로 만든다.
멤버 클래스의 인스턴스 각각이 바깥 인스턴스를 참조한다면 비정적으로, 그렇지 않으면 정적으로 만들자.
중첩 클래스가 한 메서드 안에서만 쓰이면서 그 인스틴스를 생성하는 지점이 단 한 곳이고 해당 타입으로 쓰기에 적합한 클래스나 인터페이스가 이미 있다면 익명 클래스로 만들고, 그렇지 않으면 지역 클래스로 만들자.