Item 24. 멤버 클래스는 되도록 static으로 만들라
1. 들어가기
중첩 클래스가 무엇일까요?
중첩 클래스는 다른 클래스 안에 정의된 클래스로 다음의 4가지 종류가 있습니다.
-
정적 멤버 클래스
-
비정적 멤버 클래스
-
익명 클래스
-
지역 클래스
먼저, 각 중첩 클래스의 사용법과 특징에 대해 알아봅시다.
2. 정적 멤버 클래스
정적 멤버 클래스는 보통 바깥 클래스와 함께 쓰일 때 유용한 public 도우미 클래스로 쓰입니다.
예를 들면 Calculator.Operation.PLUS
나 Calculator.Operation.MINUS
같은 형태입니다.
🔍 사용법
정적 멤버 클래스는 톱레벨 클래스의 내부에 static으로 선언한 클래스입니다.
class A{
static class B{}
}
A.B b = new B();
3. 비정적 멤버 클래스
비정적 멤버 클래스는 어댑터를 정의할 때 자주 쓰입니다.
어댑터는 클래스의 인터페이스를 사용자가 기대하는 인터페이스 형태로 적응(변환) 시키는 것을 말합니다.
🔍 사용법
비정적 멤버 클래스는 톱레벨 클래스의 내부에 static 없이 선언한 클래스입니다.
class A {
class B {}
}
A.B b = new A().new B();
4. 정적 멤버 클래스 vs 비정적 멤버 클래스
두 클래스의 차이는 단지 static의 유무이지만 의미상 차이는 의외로 꽤 큽니다.
비정적 멤버 클래스의 인스턴스는 바깥 클래스의 인스턴스와 암묵적으로 연결됩니다.
그렇기 때문에 비정적 멤버 클래스의 인스턴스 메서드에서
바깥 인스턴스의 메서드를 호출하거나 바깥 인스턴스의 참조를 가져올 수 있습니다.
따라서 static을 생략하면 바깥 인스턴스로의 숨은 참조를 가지게 되어 메모리 누수가 생길 수 있으므로
멤버 클래스에서 바깥 인스턴스에 접근할 일이 없다면 무조건 정적 멤버 클래스로 만들어야 합니다.
5. 익명 클래스
익명 클래스는 이름이 없는 클래스로, non-static 클래스입니다.
주로 즉석에서 작은 함수 객체나 처리 객체를 만드는데 사용합니다.
🔍 사용법
/* Person 클래스 */
public class Person {
void getName() {}
}
public static void main(String[] args) {
Person person = new Person() {
String name = "이상훈";
void getName() { System.out.println("이름 : " + name); }
};
person.getName();
}
이름 : 이상훈
위와 같은 구조는 상속을 사용하면 되는데 왜 굳이 익명 클래스를 사용하는걸까요?
물론, 상속 받은 객체를 여러 번 사용한다면 상속을 사용하는 것이 맞습니다.
하지만 한 번만 사용하고 버려지는 경우, 클래스 파일을 만드는 것은 메모리 낭비가 될 수 있습니다.
바로 이런 경우 익명 클래스를 사용할 수 있습니다.
6. 익명 클래스의 단점
반면, 익명 클래스는 단점이 많기 때문에 주의해서 사용해야 합니다.
익명 클래스의 단점은 다음과 같습니다.
-
선언한 지점에서만 인스턴스를 만들 수 있다.
-
instanceof 검사나 클래스의 이름이 필요한 작업은 수행할 수 없다.
-
여러 인터페이스를 구현할 수 없다.
-
인터페이스를 구현하는 동시에 다른 클래스를 상속할 수 없다.
-
익명 클래스를 사용하는 클라이언트는 해당 클래스가 상위 타입에서 상속한 멤버 외에는 호출할 수 없다.
-
익명 클래스는 표현식 중간에 등장하므로 코드가 짧지 않으면 가독성이 떨어진다.
7. 지역 클래스
지역 클래스는 블록 안에 정의된 클래스로 메서드 안에서만 클래스를 사용하고 싶을 때 사용합니다.
🔍 사용법
public void greeting() {
class KoreaGreeting { ... }
class JapanGreeting { ... }
}
지역 클래스는 지역 변수를 선언하는 곳이면 어디든지 선언할 수 있고 유효 범위도 지역 변수와 같습니다.
익명 클래스와 다르게 이름이 있어 반복해서 사용할 수 있지만,
익명 클래스처럼 static을 사용할 수 없고 가독성을 위해 짧게 작성해야 합니다.
8. 정리
이번 포스트는 4가지의 중첩 클래스의 사용법과 특징을 알아보았습니다.
중첩 클래스를 사용할 때는 각 특징에 맞게 사용합시다.
🎯 멤버 클래스 vs 내부 클래스
메서드 밖에서 사용하거나 코드가 긴 경우 => 멤버 클래스
메서드 안에서만 사용하고 코드가 길지 않은 경우 => 내부 클래스 (익명 클래스, 지역 클래스)
🎯 정적 멤버 클래스 vs 비정적 멤버 클래스
바깥 인스턴스를 참조하는 경우 => 비정적 멤버 클래스
바깥 인스턴스를 참조하지 않는 경우 => 정적 멤버 클래스
🎯 익명 클래스 vs 지역 클래스
인스턴스를 생성하는 지점이 단 한 곳인 경우 => 익명 클래스
인스턴스를 생성하는 지점이 한 곳이 아닌 경우 => 지역 클래스
9. 참고
📕 개인 기록용 블로그입니다.
😊 오타나 잘못된 정보가 있을 경우 댓글이나 메일로 말씀해주시면 바로 수정하겠습니다! 😊
댓글남기기