자바 immutable

최창효·2022년 2월 3일
post-thumbnail

immutable

  • immutable이라는 단어는 변경할 수 없는, 불변의 이라는 뜻을 가지고 있습니다.
  • 자바에서는 생성 후 그 상태를 바꿀 수 없는 객체를 immutable object라고 부릅니다.
  • 특별한 조건이 없는 경우 reference 타입의 객체는 모두 immutable object입니다.

예시

  • 다음을 생각해 봅시다.
String str = "s";
for(int i =0;i<5;i++){
	str+= "s";
}
System.out.println(str);

우리는 출력의 결과로 ssssss를 얻을 수 있습니다. 그렇다면 ssssss는 처음의 s에 값이 추가된 것일까요? 아니면 str에 ssssss이라는 새로운 값이 들어간 것일까요? 정답은 후자입니다.

  • 다음을 확인해 보겠습니다.
String str = "s";

System.out.println(System.identityHashCode(str)); 
for(int i =0;i<5;i++){
	str+= "s";
}
System.out.println(System.identityHashCode(str)); //반복문 실행 전과 다른 값을 반환합니다.
System.out.println(System.identityHashCode(str)); //str에 아무런 변화가 없다면 같은 값을 반환합니다.

위 예제에서 반복문을 시행하기 전과 후의 결과값이 다른 걸 확인할 수 있습니다.
System.identityHashCode()는 객체의 고유한 hashcode를 반환합니다.

알게된 사실

  • 우리는 String을 변경해서 쓰고 있다고 생각했지만, String은 immutable하기 때문에 계속해서 새로운 주소에 값을 만들고, 새로운 주소값을 담아내고 있었던 것입니다.
    • 우리는 str변수를 변경할 때마다 heap메모리에 새로운 값을 만들고 있었습니다.
    • 최종적으로 str이 가리키고 있는 주소를 제외한 나머지는 어떠한 변수도 참조하고 있지 않으므로 garbage상태가 됩니다.
      --> immutable한 변수를 변경해서(우리가 변경했다고 믿는것일 뿐이지만요) 사용하는 건 메모리 비효율적인 일입니다.

개선 방향

  • 그렇다면 변수를 변경할 일이 많다면 mutable한 StringbufferStringbuilder의 사용이 권장되어 집니다.
    • 둘의 차이는 동기화의 유무로 multi-thread에서 안전성의 차이를 보입니다.

추가

위에서 언급했던 System.identityHashCode()에 대해 조금 더 설명해 보겠습니다.

  • System.identityHashCode()hashCode()와 비교됩니다.
    • hasCode()는 모든 객체의 부모인 Object클래스에 정의되어 있습니다. 그래서 모든 객체에서 재정의하여 쓸 수 있습니다.
      • 실제로 위의 예제에서 HashCode()를 사용하면 System.identityHashCode()와는 다른 결과를 출력합니다. 그 이유는 String에서 HashCode()를 오버라이드(재정의)하고 있기 때문입니다.
    • 하지만 System.identityHashCode() 오버라이드가 불가능하며 객체마다의 고유한 HashCode를 반환합니다.

요약

  • String은 immutable해 값을 변경시킬 때마다 새로운 객체를 생성해 메모리 비효율적이다.
  • 값을 변경할꺼면 mutable한 Stringbuffer나 Stringbuilder를 쓰자.
  • multi-thread환경이 아니라면 StringBuilder를 추천(단일스레드에서 더 뛰어남).
profile
기록하고 정리하는 걸 좋아하는 백엔드 개발자입니다.

0개의 댓글