static 클래스 및 변수 메소드등이 메모리에 적재되는 시점과 Static Inner 클래스를 사용해야하는 이유
여러 책에서 static 클래스가 메모리에 적재되는 시점은 클래스 로더를 통해서 Application이 실행 될 때 메모리에 올라가는 것으로 이해하는 경우가 많다.
하지만 이 경우는 final 키워드를 사용하여 Constant Pool 에서 관리되는 경우에 해당하고, 실제 static 키워드를 사용한 inner 클래스는 일반적인 클래스와 동일하게 생성자 혹은 블럭을 통해 생성되거나 static 변수 혹은 메서드등이 사용되는 시점에 최초로 메모리에 적재되는 것이다. (JDK8 이전에는 사용되지 않는 static 변수 혹은 메서드, 컬렉션 등이 GC 대상에 포함되지 않아 memory leak가 발생하는 문제가 있었지만, 이후 Heap 영역의 Meta Space 영역으로 이동하게 되면서, GC 대상이 되었다.) static Inner 클래스를 사용해야 하는 이유는 디컴파일 된 코드를 보면 쉽게 이해 할 수 있다.
public class Outer_Class {
int field = 10;
class Inner_Class {
int inner_field = 20;
}
}
위의 코드를 컴파일하고 생성된 Outer_Class$Inner_Class 파일을 디컴파일해보면 다음과 같은 결과를 볼 수 있다.
class Outer_Class$Inner_Class {
int inner_field = 10;
Outer_Class$Inner_Class(Outer_Class this$0) {
this.this$0 = this$0;
this.inner_field = 20;
}
}
위 처럼 Inner 클래스를 생성 할 때, Outer클래스가 생성자 매개변수가 들어와 Inner 클래스가 Outer 클래스를 의존하여, Inner 클래스가 GC를 통해 메모리가 비워지기 전까지 Outer 클래스는 GC가 이루어질 수 없다. 이는 결국 메모리 leak 를 발생시키게 된다.
하지만 static inner class를 사용하게 되면 디컴파일 했을 때 다음과 같이 나타나게 된다.
class Outer_Class$Inner_Class {
int inner_field = 20;
Outer_Class$Inner_Class() {
}
}
다음처럼 생성자의 매개변수에 Outer 클래스를 의존하지 않는 모습을 볼 수 있다. 이에 따라 Outer Class와 static Inner Class는 각자 독립적으로 GC의 대상이 되기 때문에 메모리 누수가 발생하지 않는 것이다. 이러한 이유로 인해 우리는 static class 를 사용해야 한다.
Optional orElse와 orElseGet 의 차이
이 부분에 대해서 별다른 차이가 없을 거라 생각하고 사용하고 있었지만, 둘 사이에서는 생각보다 많은 차이점이 존재했다. 하지만 그 차이점이 생각보다 어렵진 않다.
String username = "이름";
String result1 = Optional.ofNullable(username).orElse("no name");
System.out.println(result1);
String result2 = Optional.ofNullable(username).orElseGet(() -> "no name");
System.out.println(result2);
위의 코드를 살펴보자. 둘의 코드는 별다른 차이가 없어보인다. 하지만 굉장히 큰 차이가 하나 존재한다.
먼저 orElse 에 대해서 살펴보자면 값이 null이면 else 에 있는 로직을 실행한다고 생각할 수 있다. 하지만 orElse의 문제는 Optional로 반환된 객체가 null이 아니더라도 else 문을 실행하게 된다. 따라서, 쓸모없는 성능 낭비가 발생을 하게 된다.
하지만 orElseGet()의 경우는 우리가 원래 예상하던 것과 동일하게 동작을 한다. 바로 null 객체가 들어올 경우에만 orElseGet() 의 Supplier 로직을 실행하게 된다. 따라서 orElse를 지양하고 orElseGet()을 무조건 사용해야 한다는 사실을 깨달았다.
참고 자료
[Optional의 orElse와 orElseGet의 차이]
회고
어느새 데브코스를 시작한지 거의 11일이 지났다. 오늘 TIL이 9회인것은 사실 첫 주차에는 토, 일 동안 프로그래머스 데브코스에 대한 주제가 아닌 다른 주제로 포스팅을 했기 때문이다! 그래도 11일자 라고 적어야하나? 이번 주차에는 토일 동안 썼으니 통일성이 깨져서 좀 그렇지만 그냥 단순하게 지금 처럼 유지해야겠다.
11일이라는 시간이 정말 무섭도록 빨리 지나갔다. 정말 바쁘고 피곤하지만 그럼에도 불구하고 정말 행복하다. 데브코스에 들어와서 내가 이루고자 했던 목표들이 하나 하나 이루어지고 있다. 무엇보다 제일 좋은 것은 Pre팀분들을 잘 만나서 그런 것 같기도 하다! 정말 다들 잘하시는 분들이고 그걸 보면서 항상 더 열심히해야겠다는 의지를 가지고 계속해서 공부를 하게 된다. 최근에 팀 면담이 진행됐는데 멘토님이 하신 말씀이 우리 팀원들이 다 똑같은 말을 했다. "우리 팀원들이 너무 잘해서... 더 열심히해야겠다는 생각이에요. 저는 실력이 상대적으로 부족한 것 같아요." 라는 말을 했다고 한다. 뭔가 다들 겸손한 생각을 가지고 계속 공부하려고 하는 의지때문 인 것 같기도 하고 실제로 다들 너무 열심히 하시기도 한다! 항상 평일 주말 상관없이 밤 늦게 까지 모여서 공부하는 우리 네이비팀 짱짱! 앞으로 1주일 동안만 Pre팀이 더 유지가 되고 이후에 New 팀으로 넘어가게 되는데 지금 팀... 벌써 너무 정이 들어버렸다. 하지만 팀원들끼리 계속해서 진행되는 스터디가 있으니 또 약간 친정으로 돌아온 느낌으로 공부를 할 수 있을 것 같다!
'프로그래머스 데브코스' 카테고리의 다른 글
프로그래머스 데브코스 11일차 - 싱글톤 패턴 (0) | 2023.06.16 |
---|---|
프로그래머스 데브코스 10일차 - 팩토리 패턴 (2) | 2023.06.14 |
프로그래머스 데브코스 8일차 - Null 제거와, Pattern 객체 캐싱 (1) | 2023.06.11 |
프로그래머스 데브코스 7일차 - 롬복 트러블 슈팅, Enum 최적화 (1) | 2023.06.10 |
프로그래머스 데브코스 6일차 - 전략패턴 (3) | 2023.06.08 |