///
Search
💡

item 24. 멤버 클래스는 되도록 static으로 만들라

중첩 클래스란 (nested class)

하나의 클래스 안에 정의된 다른 클래스를 이야기한다. 중첩 클래스는 자신을 감싼 바깥 객체에서만 쓰여야 하며, 그 외의 용도가 있다면 톱레벨 클래스로 만들어야 한다.

정적 멤버 클래스 (static member class)

class Parent { private String familyName; static class Child { private String familyName; public Child(Parent parent) { // 바깥 객체의 private 필드에 접근 가능하다. this.familyName = parent.familyName; } } } //main 문 public static void main(String[] args) { Parent.Child child = new Parent.Child(); }
Java
복사
부모 객체의 private 필드에 접근할 수 있다는 점, 내부 객체가 호출되는 시점에 클래스가 로드된다는 점만 제외하면 탑레벨 클래스와 같다. 컴패니언 객체로 자주 쓰이며 (Builder를 떠올려 보자) 다른 정적 멤버와 똑같은 접근 규칙을 적용받는다.

멤버 클래스 (instance member class)

class Parent { private String familyName; class Child { private String familyName; public Child(Parent parent) { // 바깥 객체의 private 필드에 접근 가능하다. this.familyName = parent.familyName; } } } //main 문 public static void main(String[] args) { // 바깥 객체가 있어야만 호출이 가능하다 Parent.Child child = new Parent().Child(); }
Java
복사
바깥 인스턴스와 비정적 멤버클래스는 암묵적으로 연결된다. 그러므로 this. 를 활용할 수 있게 된다. 그 말은, 바깥 인스턴스가 있어야만 생성이 가능하다는 것이다. 자신의 반복자를 구현하는 데 쓰이는 경우가 있다고 한다.
public class MySet<E> extends AbstractSet<E> { ... public Iterator<E> iterator(){ return new MyIterator(); } private class MyIterator implements Iterator<E> { ... } }
Java
복사
하지만 바깥 인스턴스에 접근할 일이 없다면 무조건 정적 메서드로 만들자. (이번 꼭지의 핵심) 외부 객체를 향한 숨은 참조가 생기고, 메모리 누수의 원인이 된다.

익명 클래스 (anonymous class)

익명 클래스는 선언한 지점에서 만드는 구현체다. 인터페이스를 사용단에서 직접 구현하거나, 단 한번만 사용될 Override용 코드를 활용할 때 쓰인다.
class Duck { public void quack(){ System.out.println("quack") } } public static void main(String[] args) { Duck duck = new Duck() { @Override public void quack(){ System.out.println("QQQQQQUUUUAAAACCCKKK!!!!!!!!!!!!!!") } } duck.quack(); }
Java
복사
람다가 생긴 후 잘 쓰이지 않게 되었다.

지역 클래스 (inner class)

지역클래스는 지역변수와 마찬가지로, 일회성으로 클래스를 선언할 수 있는 문법이다. 생명 주기도 지역변수와 동일하다. 추상화, 캡슐화, 재사용성을 상징하는 클래스를 변수처럼 쓰는 건… 평생 안 쓸 듯 하다.
public static void main(String[] args) { class MyClass{ } MyClass myClass = new MyClass(); }
Java
복사