ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 24. 멤버 클래스는 되도록 static으로 만들라
    JAVA/Effective java 2021. 3. 8. 14:19
    • 중첩 클래스란 다른 클래스 안에 정의된 클래스를 말한다.
    • 중첩 클래스의 종류는 정적 멤버 클래스, (비정적) 멤버 클래스, 익명 클래스, 지역 클래스, 이렇게 네 가지다.
    • 이번 아이템에서는 각각의 중첩 클래스를 언제 그리고 왜 사용해야 하는지 이야기한다.

     

     

    정적 멤버 클래스와 비정적 멤버 클래스


    • 정적 멤버 클래스는 다른 클래스 안에 선언되고, 바깥 클래스의 private 멤버에도 접근할 수 있다는 점만 제외하고는 일반 클래스와 똑같다.
    • 정적 멤버 클래스는 흔히 바깥 클래스와 함께 쓰일 때만 유용한 public 도우미 클래스로 쓰인다.

     

    • 계산기가 지원하는 연산 종류를 정의하는 열거 타입을 예로 생각해보자. Operation 열거 타입은 Calculator 클래스의 public 정적 멤버 클래스가 되어야 한다.
    • 그러면 Calculator 클라이언트에서 Calculator.Operation.PLUS 나 Calculator.Operation.MINUS 같은 형태로 원하는 연산을 참조할 수 있다. (아이템 34)

     

     

     

    • 정적 멤버 클래스와 비정적 멤버 클래스의 구문상 차이는 단지 static이 붙어있고 없고 뿐이지만, 의미상 차이는 꽤 크다.
    • 비정적 멤버 클래스의 인스턴스는 바깥 클래스의 인스턴스와 암묵적으로 연결된다.

    • 따라서 비정적 멤버 클래스의 인스턴스 메서드에서 정규화된 this를 사용해 바깥 인스턴스의 메서드를 호출하거나 바깥 인스턴스의 참조를 가져올 수 있다.
    • 정규화된 this란 클래스명.this 형태로 바깥 클래스의 이름을 명시하는 용법을 말한다.

     

    • 따라서 개념상 중첩 클래스의 인스턴스가 바깥 인스턴스와 독립적으로 존재할 수 있다면 정적 멤버 클래스로 만들어야 한다.

    • 비정적 멤버 클래스는 바깥 인스턴스 없이는 생성할 수 없기 때문이다.

     

     

    • 비정적 멤버 클래스는 어댑터를 정의할 때 자주 쓰인다.
    • 즉 어떤 클래스의 인스턴스를 감싸 다른 클래스의 인스턴스처럼 보이게 하는 뷰로 사용하는 것이다.

    HashMap class

    • 예컨대 Map 인터페이스의 구현체들은 보통 ( keySet, entrySet,  values 메서드가 반환하는 ) 자신의 컬렉션 뷰를 구현할 때 비정적 멤버 클래스를 사용한다.
    • 비슷하게 Set과 List 같은 다른 컬렉션 인터페이스 구현들도 자신의 반복자를 구현할 때 비정적 멤버 클래스를 주로 사용한다.

     

     

     

    • 멤버 클래스에서 바깥 인스턴스에 접근할 일이 없다면 무조건 static을 붙여서 정적 멤버 클래스로 만들자.
    • static 을 생략하면 바깥 인스턴스로의 숨은 외부 참조를 갖게 된다. 
    • 이 참조를 저장하려면 시간과 공간이 소비된다. 더 심각한 문제는 가비지 컬렉션이 바깥 클래스의 인스턴스를 수거하지 못하는 메모리 누수로 이어질 수 있다.

     

    • Map 인스턴스를 예로 많은 Map 구현체는 키-값 쌍을 표현하는 엔트리 객체들을 가진다.
    • 모든 엔트리가 맵과 연관되어 있지만 엔트리의 메서드들(getKey, getValue, setValue)는 맵을 직접 사용하지는 않는다.
    • 따라서 엔트리를 비정적 멤버 클래스로 표현하는 것은 낭비고, private 정적 멤버 클래스가 가장 알맞다.

     

     

     

     

    익명 클래스


    • 익명 클래스는 멤버와 달리, 쓰이는 시점에 선언과 동시에 인스턴스가 만들어진다. 
    • 오직 비정적인 문맥에서 사용될 때만 바깥 클래스의 인스턴스를 참조할 수 있다.
    • 익명 클래스는 표현식 중간에 등장하므로 짧지 않으면 가독성이 떨어진다. 
    • 자바가 람다를 지원한 이후로는 작은 함수 객체나 처리 객체는 람다를 이용해서 처리되고 있다.

     

     

     

     

     

    지역 클래스


    • 지역 클래스는 지역 변수를 선언할 수 있는 곳이면 실질적으로 어디서든 선언할 수 있고, 유효 범위도 지역변수와 같다.
    • 다른 세 중첩 클래스와의 공통점도 하나씩 가지고 있다.
    • 익명 클래스처럼 비정적 문맥에서 사용될 때만 바깥 인스턴스를 참조할 수 있으며, 정적 멤버는 가질 수 없고 가독성을 위해 짧게 작성해야 한다.

     

     

     

    핵심 정리

     


    • 중첩 클래스에는 네 가지가 있으며 각각의 쓰임이 다르다.
    • 메서드 밖에서도 사용해야 하거나 메서드 안에 정의하기에 너무 길다면 멤버 클래스로 만든다.
    • 멤버 클래스의 인스턴스 각각이 바깥 인스턴스를 참조한다면 비정적으로, 그렇지 않으면 정적으로 만들자.
    • 중첩 클래스가 한 메서드 안에서만 쓰이면서 그 인스턴스를 생성하는 지점이 단 한 곳이고 해당 타입으로 쓰기에 적합한 클래스나 인터페이스가 이미 있다면 익명 클래스로 만들고, 그렇지 않다면 지역 클래스로 만들자.

     

     

    참고 자료 


    이펙티브 자바

Designed by Tistory.