[Item24] Nested Class
멤버 클래스를 왜 static으로 만들어야 하는가, 그전에 멤버 클래스는 왜 필요한가?
책에서는 멤버 클래스를 가지고 있는 클래스에서만 쓰여야 한다고 한다
Oracle 문서에서는 다음과 같이 설명한다
한 곳에서만 쓰일 녀석들을 논리적으로 묶기 위함 & 캡슐화, 가독성, 유지보수성 향상
즉 outer class 와 함께 쓰일 때만 의미 있는 클래스로써 도우미 역할을 한다
예를 들어 outer class에서 쓰일 상수 클래스가 있을 때, outer class 외에 쓰일 일이 전혀 없으면 top-level로 빼기엔 애매하다
더욱이 유지 보수를 위해서 개념적으로 가깝다면 물리적으로 가까이 두는 것이 좋다
이런 경우 inner class로 두면 응집력이 높고 결합도가 낮은 형태로 만들 수 있다
중첩 클래스엔 네 종류가 있다
1. static class
2. non-static class
3. anonymous class
4. local class
이를 다시 세분화해 두 가지로 나눈다
1. static nested class
2. inner class
정적 클래스를 제외하고는 전부 inner class에 해당한다
네 가지 중 가능하다면 static으로 만들라는 건데 왜일까?
non-static으로 만들면 암묵적으로 outer class에 대한 숨은 참조를 갖기 때문이다
숨은 참조를 갖고 있다면 참조에 대한 관계 정보를 따로 저장해야 하기 때문에 추가 메모리 공간이 든다
non-static class를 생성할 때 참조 정보를 저장하게 된다
더 심각한 문제로 GC는 더 이상 참조되지 않는 객체를 수거하기 때문에 숨은 참조의 영향으로 outer class는 수거되지 않는다
추가 메모리 소모도 물론 가벼운 문제는 아니지만 GC가 수거하지 못한다는 게 큰 문제다
메모리 누수는 발견하기 쉽지 않고 고수가 아닌 이상에야 코드 한 번 째려보고 어느 포인트에서 누수가 나는지 알기 힘들다
따라서 기본은 static 으로 전부 깔자
inner class에서 outer class로 접근해야 할 일이 있다면 top-level로 빼는 게 나을지 먼저 고민하자
익명 클래스는 메서드의 인자로 넘기기 위해 사용하는 방식이다
boiler plate가 많아져 가독성이 좋지 않고 익명이라는 말 그대로 이름이 없어 타입 검사도 수행할 수 없다
다행히 자바8부터 람다로 거의 대체할 수 있다
다만 익명 클래스가 반드시 필요한 경우가 있는데 익명 클래스의 메서드 중 익명 클래스를 다시 넘겨야 하는 경우가 있다
이때 this로 넘겨야 하는데, 람다에서 this는 람다를 의미하는 것이 아닌 메서드 자체를 의미하게 되므로
이 경우엔 익명 클래스를 사용해야 한다, 보통 관찰자 패턴에서 자기 자신을 구독 해지할 때 사용한다고 한다
local class는 모르고 지내도록 하자