Nested Class 에 언제 static 을 붙여야 할까?
이전 DTO 는 어떻게 구성하고, 변환해야 할까? 글에 이어서 dto 를 inner class 로 묶을 때, 각 class 에 static 을 붙여주는 것이 좋은데, 이 상황에서 왜 static 을 붙이는 것이 좋은지 설명하려다 보니 Java 의 Nested Class 부터 알고 넘어가면 좋을 것 같아 정리하게 되었다.
- Nested Classes, Terminology (이동)
- Nested Classes 를 왜 사용하는가? (이동)
- Inner Classes (이동)
- Static Nested Classes (이동)
- DTO 를 Nested Classes 로 묶을 때 왜 static 을 붙이는 것이 좋은가? (이동)
1 ~ 4 까지는 oracle 의 공식 문서에서 필요한 내용을 번역한 것이며, 5번이 결론이다. (직역보다는 제 생각을 더하여 작성하였으니, 본문은 '참고자료' 에서 확인하시면 좋을 것 같습니다.)
1. Nested Classes, Terminology
Java 에서는 다음과 같이 내부에 다른 class 를 포함하며 class 를 정의할 수 있으며, 이러한 class 를 nested class 라고 부른다.
Nested classes 들은 non-static 과 static 으로 나뉘는데, 이 때 Non-static nested classes 들을 inner classes 라고 부르며, static 으로 선언된 nested classes 들을 static nested classes 라고 부른다.
- Non-static nested classes 들은 함께 포함되어 있는 다른 class 의 member 들에 접근할 수 있다. (해당 class 가 private 이라 하더라도)
- 그에 반해 Static nested classes 들은 다른 class 의 member 에 접근할 수 없다.
2. Nested Classes 를 왜 사용하는가?
- 한 곳에서 사용되는 classes 들을 논리적으로 묶어 패키지를 더욱 간소화할 수 있다.
- 더 가독성이 좋고, 유지보수가 용이한 코드를 만들 수 있다.
3. Inner Classes
inner class 는 '인스턴스 메소드, 변수' 처럼 inner class 를 포함하는 클래스의 인스턴스에 연결되어 있으며, 때문에 해당 객체의 메소드, 필드에 직접 접근할 수 있다. (클래스 메소드 vs 인스턴스 메소드)
inner class 의 인스턴스는 outer class 의 인스턴스가 존재해야만 존재할 수 있다. 때문에 inner class 를 인스턴스화 하고 싶다면, outer class 를 먼저 인스턴스화 해야한다.
4. Static Nested Classes
static nested class 는 '클래스 메소드, 변수' 처럼 행동하며, 때문에 outer class 가 포함하는 다른 클래스에서 정의된 인스턴스 메소드, 변수에 직접 접근할 수 없다. (클래스 메소드 vs 인스턴스 메소드, 위와 동일한 링크)
static nested class 는 다른 최상위 클래스들처럼 outer class 및 다른 클래스들의 인스턴스 member 와 상호작용을 한다. 실질적으로 static nested class 는 패키징 편의를 위해 최상위 클래스에 nested 된 최상위 클래스이다. (outer class 에 nested 되어 있지만, 어쨋든 최상위 클래스 처럼 행동할 수 있으니)
때문에 static nested class 는 위와 같이 바로 인스턴스화가 가능하다.
5. DTO 를 Nested Classes 로 묶을 때 왜 static 을 붙이는 것이 좋은가?
1 ~ 4 번까지는 nested class 에 대한 이야기였고, 다시 dto class 에 대한 이야기로 돌아오자 (DTO 는 어떻게 구성하고, 변환해야 할까?). 앞서 말했다시피, dto classes 들을 nested classes 로 관리한다고 했다. 이 때 클래스에 static 을 붙여주지 않으면 위 이미지와 같은 warning 이 표시된다.
왜 그런지에 대한 자세한 이유는 Java 의 내부 클래스는 static 으로 선언하자 에서 '이펙티브 자바' 도서를 참고하여 잘 설명해주고 있어서 대신 첨부한다. 간단히 요약하자면
- Inner class (Non-static nested class) 는 Outer class 의 인스턴스화 이후 Inner class 의 인스턴스화가 가능하며
- 두 인스턴스의 관계정보는 Inner class의 인스턴스 안에 만들어져 메모리 공간을 더 차지하며, 생성시간도 더 걸린다.
- 더 심각한 문제는 Inner class 가 Outer class 인스턴스에 대한 참조를 갖고 있기 때문에, Garbage Collection 은 Outer class 의 인스턴스를 수거 대상으로 보지 않아 GC 의 대상에서 빠지게 된다. (더 쉽게 풀어쓰자면 inner class, outer class 두 인스턴스가 연결되어 있어서 outer class 인스턴스의 메모리를 못 뺏는 것)
- 때문에 Outer class 를 참조할 일이 없다면, Nested class 는 static 을 붙여 무조건 static nested class 를 만들자
정적, 비정적 내부 클래스 알고 사용하기 에서 static, non-static 에 따라 GC 가 올바르게 되고 있는지 실제 확인한 결과가 있으니 확인해보면 많은 도움이 될 거 같다.
1. [링크] DTO 를 사용해야 하는 이유
2. [링크] DTO 는 어떻게 구성하고, 변환해야 할까?
3. [링크] Nested Class 에 언제 static 을 붙여야 할까?
https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
https://www.geeksforgeeks.org/difference-between-static-and-non-static-nested-class-in-java/
http://www.tcpschool.com/java/java_member_method
https://johngrib.github.io/wiki/java-inner-class-may-be-static/
https://tecoble.techcourse.co.kr/post/2020-11-05-nested-class/