[Effective Java] 멤버 클래스는 되도록 static으로 만들라

중첩 클래스

중첩 클래스는 자신을 감싼 외부 클래스에서만 쓰여야 하며 그 외에 쓰임새가 있다면 톱레벨 클래스로 만들어야 한다.

public static member class

public static member class는 내부 클래스로 선언되며 외부 클래스의 private 멤버에 접근이 가능하다는 점만 제외하면 일반 클래스와 동일하다.

private static member class

private static member class는 흔히 외부 클래스가 표현하는 객체의 한 부분을 나타낼 때 쓴다.

non-static member class

non-static member class의 인스턴스는 암묵적으로 외부 클래스와 연결된다. 그렇기 때문에 정규화된 this(OutterClass.this) 형태로 외부 클래스의 메소드를 호출하거나 인스턴스 참조가 가능하다. 따라서 외부 클래스와 독립적으로 존재할 수 있다면 정적 멤버 클래스로 만들어야 한다. 비정적 멤버 클래스와 외부 클래스와의 관계는 멤버 클래스가 인스턴스화 될 때 확립되며 변경이 불가능하다. 멤버 클래스에서 외부 인스턴스에 접근할 일이 없다면 무조건 static을 붙혀서 정적 멤버 클래스로 만들자. static을 생략하면 외부 인스턴스로의 숨은 외부 참조를 갖게 되며 GC가 외부 클래스의 참조를 찾지 못하게 되어 memory leak이 생길 수 있다는 점이다. 그리고 외부 인스턴스를 숨은 참조를 하기 때문에 공간과 시간이 낭비된다.

local class

local class는 가장 드물게 사용되는 중첩 클래스다. 지역변수를 선언할 수 있는 곳이면 실질적으로 어느 곳이든 선언할 수 있고 유효 범위도 지역변수와 같다. 멤버 클래스처럼 이름이 있고 반복해서 사용할 수 있으며, 익명 클래스 처럼 비정적 문맥에서 사용될 때만 외부 인스턴스를 참조할 수 있으며, 정적 멤버는 가질 수 없으며, 가독성을 위해 짧게 작성해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class SomeClass {
public static class SomePublicStaticClass{
public void someMethod() {
SomeClass someClass = new SomeClass();
//private지만 접근 가능
someClass.printThis();
}
}

//외부에서 접근 불가
private static class SomePrivateStaticClass{
public void someMethod() {
SomeClass someClass = new SomeClass();

//private지만 접근 가능
someClass.printThis();
}
}

private class SomePrivateNonStaticClass {
public SomePrivateNonStaticClass() {
System.out.println("SomePrivateNonStaticClass Constructor");
}
public void someMethod() {
SomeClass.this.someMethod();
}
}

public class SomePublicNonStaticClass {
public SomePublicNonStaticClass() {
System.out.println("SomePublicNonStaticClass Constructor");
}
public void someMethod() {
printThis();
System.out.println(this);
}
}

//다른 클래스의 인스턴스처럼 보이게 하는 효과
public SomePrivateNonStaticClass getSomePrivateNonStaticClass() {
return new SomePrivateNonStaticClass();
}

//다른 클래스의 인스턴스처럼 보이게 하는 효과
public SomePublicNonStaticClass getSomePublicNonStaticClass() {
return new SomePublicNonStaticClass();
}

public SomeClass() {
System.out.println("SomeClass Constructor");
}

public void printThis() {
System.out.println(this);
}

public void someMethod() {
class SomeLocalClass {
public SomeLocalClass() {
System.out.println("SomeLocalClass Constructor");
}
}

SomeLocalClass someLocalClass = new SomeLocalClass();
}
}

Author: Song Hayoung
Link: https://songhayoung.github.io/2020/08/09/Languages/Effective%20JAVA/item24/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.