https://www.infoworld.com/article/2255920/avoid-memory-leaks-in-inner-classes.html
중첩 클래스(nested class)?
- 다른 클래스 안에 정의된 클래스를 말한다.
- 자신을 감싼 바깥 클래스에서만 쓰여야 하며, 그 외의 쓰임새가 있다면 톱레벨 클래스로 만들어야 한다.
public class EnclosingClass { // 바깥 클래스
public class EnclosedClass // 중첩 클래스
}
중첩 클래스의 종류
- 정적 멤버 클래스
- (비정적)멤버 클래스
- 익명 클래스
- 지역 클래스
정적 멤버 클래스?
- 클래스에 static을 붙인다.
- 다른 클래스 안에 선언되고, 바깥 클래스의 private 멤버에도 접근할 수 있다는 점만 제외하고 일반 클래스와 같다.
- 흔히 바깥 클래스와 함께 쓰일 때만 유용한 public 도우미 클래스로 쓰인다.
(비정적)멤버 클래스?
- 어댑터를 정의할 때 자주 쓰인다. 다른 클래스의 인스턴스처럼 보이게 하는 뷰로 사용한다.
- 멤버 클래스의 인스턴스는 바깥 클래스의 인스턴스와 암묵적으로 연결된다.
- 멤버 클래스에서 바깥 인스턴스(this)에 접근할 일이 없다면 무조건 static을 붙여서 정적 멤버 클래스로 만들자.
- static을 생략했을 경우 바깥 인스턴스로의 숨은 외부 참조를 갖게되어 가비지 컬렉션이 바깥 클래스의 인스턴스를 수거하지 못해 메모리 누수가 생길 수 있다.
InnerOuter outer = new InnerOuter();
InnerOuter.Inner inner = outer.new Inner();
익명 클래스?
- 익명 클래스는 바깥 클래스의 멤버가 아니다. 멤버와 달리 쓰이는 시점에 선언과 동시에 인스턴스가 만들어진다.
- 람다를 지원하기 전에는 즉석에서 작은 함수 객체나 처리 객체를 만드는 데 익명 클래스를 주로 사용했다.
- 정적 팩터리 메서드를 구현할 때 사용된다.(item20. 20-1 intArrayAsList 참고)
지역 클래스?
- 지역변수를 선언할 수 있는 곳이면 실질적으로 어디서든 선언할 수 있고, 유효 범위도 지역변수와 같다.
- 멤버 클래스처럼 이름이 있고 반복해서 사용할 수 있다.
- 익명클래스처럼 비정적 문맥에서 사용될 때만 바깥 이느턴스를 참조할 수 있다.
- 정적멤버는 가질 수 없으며, 가독성을 위해 짧게 작성해야 한다.
var thread = new Thread(( -> {
...
}))
정리
- 메서드 밖에서도 사용해야하거나 메서드 안에 정의하기엔 너무 길다면 멤버 클래스로 만든다.
- 멤버 클래스의 인스턴스 각각이 바깥 인스턴스를 참조한다면 비정적으로, 그렇지 않으면 정적으로 만들자.
- 중첩 클래스가 한 메서드 안에서만 쓰이면서 그 인스턴스를 생성하는 지점이 단 한곳이고 해당 타입으로 쓰기에 적합한 클래스나 인터페이스가 이미 있다면 익명 클래스로 만들고, 그렇지 않으면 지역 클래스로 만들자
'Java > EffectiveJava' 카테고리의 다른 글
Effective Java Item26. 로 타입은 사용하지 말라. (0) | 2025.01.24 |
---|---|
Effective Java Item20. 추상 클래스보다는 인터페이스를 우선하라. (0) | 2025.01.18 |
Effective Java Item18. 상속보다는 컴포지션을 사용하라. (0) | 2025.01.15 |
Effective Java Item8. finalizer와 cleaner 사용을 피하라 (0) | 2025.01.12 |
Effective Java Item5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2025.01.12 |