Developer Sang Guy

[Java]NonStaticInnerClass vs StaticInnerClass 본문

Java

[Java]NonStaticInnerClass vs StaticInnerClass

은크 2022. 5. 18. 14:45

NonStaticInnerClass

- 상위 클래스를 참조해야 생성 및 사용 가능 (숨은 참조가 생성 됨)

- 외부 클래스의 자원을 사용 할 수 있음 (참조했으니까 사용 가능)

- 외부 클래스를 필수적으로 참조하므로 매번 시간과 공간이 소비되며

  가비지 걸렉션이 외부 클래스의 인스턴스를 수거하지 못하는 메모리 누수가 생길 수 있다.

  위와 같은 사유로 외부 클래스의 자원을 사용 할 일이 없다면 무조건 static을 붙여 멤버 클래스를 만들도록 권유한다.

 

StaticInnerClass

- 상위 클래스 참조 필요없이 생성 및 사용 가능 (숨은 참조 그딴거 없음)

- 외부 클래스의 자원을 사용 할 수 없음 (Static이라서 사용 못함)

 

내부 클래스를 가진 TestClass

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
public class TestClass {
    
    public void add(int a, int b) {
        
        System.out.println(a + b);
    }
    
    public class NonStaticClass {
        
        private String name;
        private String age;
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getAge() {
            return age;
        }
        public void setAge(String age) {
            this.age = age;
        }
        
        public void nscAdd() {
            
            // 외부 클래스 자원 사용 가능
            add(12);
        }
    }
    
    public static class StaticClass {
        
        private String name;
        private String age;
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getAge() {
            return age;
        }
        public void setAge(String age) {
            this.age = age;
        }
        
        public void scAdd() {
            
            // 외부 클래스 자원 사용 불가 (컴파일 에러)
            add(12);
        }
    }
}
cs

 

실행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class TestMain {
    
    public static void main(String[] args) throws Exception {
        
        TestClass.NonStaticClass nsc = new TestClass().new NonStaticClass();
        nsc.setName("비정적 내부 클래스");
        System.out.println(nsc.getName());
        getClassFieldInfo(nsc);
        
        System.out.println("-------------------------------------------------------------------------");
        
        TestClass.StaticClass sc = new TestClass.StaticClass();
        sc.setName("정적 내부 클래스");
        System.out.println(sc.getName());        
        getClassFieldInfo(sc);
    }
    
    public static void getClassFieldInfo(Object obj) throws Exception {
        
        for (Field field : obj.getClass().getDeclaredFields()) {
            System.out.println(obj + " / " + field.getName());
        }
    }
}
cs

 

결과

1
2
3
4
5
6
7
8
9
비정적 내부 클래스
com.example.demo.innerclass.TestClass$NonStaticClass@626b2d4a / name
com.example.demo.innerclass.TestClass$NonStaticClass@626b2d4a / age
com.example.demo.innerclass.TestClass$NonStaticClass@626b2d4a / this$0 <-- 외부(상위) 클래스 숨은 참조
-------------------------------------------------------------------------
정적 내부 클래스
com.example.demo.innerclass.TestClass$StaticClass@379619aa / name
com.example.demo.innerclass.TestClass$StaticClass@379619aa / age
 
cs

 

StaticInnerClass는 Static이면 Method 영역에 적재 된 메모리를 공유하는 상태라서 멀티 스레드 환경에서는 조심히 사용해야 하는 것이 아닐까??

자바의 Static에 대해서 알고있다면 위와 같은 의문을 가질 수 있다.

Static이 붙은 객체 또는 필드의 경우 JVM Loading 시 Method 영역에 메모리가 적재되어 모든 스레드에서 해당 자원을 공유하게 된다.

 

하지만 클래스의 경우 그 기능이 다르다.

Static이 붙은 Inner Class의 경우 해당 클래스의 메모리가 적재되어 모든 스레드에서 공유하는 것이 아닌 외부(상위) 클래스 참조 없이 생성 및 사용이 가능한 상태이다.

 

실행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args) throws Exception {
        
        TestClass.StaticClass sc = new TestClass.StaticClass();
        sc.setName("정적 내부 클래스1");
        System.out.println(sc.getName());        
        getClassFieldInfo(sc);
        
        System.out.println("-------------------------------------------------------------------------");
        
        TestClass.StaticClass scc = new TestClass.StaticClass();
        scc.setName("정적 내부 클래스2");
        System.out.println(scc.getName());        
        getClassFieldInfo(scc);
        
        System.out.println("-------------------------------------------------------------------------");
        
        if (sc.equals(scc)) System.out.println("같다");
        else System.out.println("다르다");
    }
cs

 

결과

1
2
3
4
5
6
7
8
9
10
정적 내부 클래스1
com.example.demo.innerclass.TestClass$StaticClass@515f550a / name
com.example.demo.innerclass.TestClass$StaticClass@515f550a / age
-------------------------------------------------------------------------
정적 내부 클래스2
com.example.demo.innerclass.TestClass$StaticClass@626b2d4a / name
com.example.demo.innerclass.TestClass$StaticClass@626b2d4a / age
-------------------------------------------------------------------------
다르다
 
cs

'Java' 카테고리의 다른 글

Checked Exception, Unchecked Exception  (1) 2022.11.26
데이터 압축  (0) 2022.05.26
Java Graphql Client 구현  (0) 2022.03.30
Java Http Rest 통신 소스  (0) 2022.01.05
Java Singleton 객체 구현 및 주의 사항  (0) 2021.05.16
Comments