말 그대로 한 번 만들어지면 절대 바뀌지 않는 객체이다
불변객체의 장점?
여러 쓰레드가 동시에 읽어도 값이 바뀌지않으니까 동기화가 필요없다.
따라서 신뢰할 수 있고 공유해도 안전하다
불변객체의 단점?
값이 바뀔 때 마다 새 객체가 생성된다
메모리를 더 쓰지만, 안쓰는 객체는 GC가 정리하므로 대부분 문제가 되지 않는다
concat이나 uppercase같은거 하더라도 String은 불변객체니까 반드시 반환을 받아줄 변수가 필요하다!
Primityive Type(원시형) : 변수에 실제 값이 들어간다. -> 객체가 아니다
Reference Type(참조형) : 변수에 객체의 주소 (참조값)이 들어간다
레퍼런스가 레퍼런스를 불러오는경우에 값이 마음대로 바뀔 수 있음
final을추가하고 , setter를 없앰으로써 immutable
만일 final 속성을 setter로 건드리려고하면 에러가 발생한다 final 키워드 붙은걸 조작하려고 하기때문임.
withXXX()를 관례적으로 사용한다 기존 인스턴스 값은 그대로 유지하되 바뀐 값을 가진 새 인스턴스를 반환한다.
반드시 return 값으로 new ImmutableReference(~)
그럼 이를 받아오는 데서도 같은 타입으로 받아와야 (= 반환값을 받아와야) 변경이 된다. 그렇지않으면 withXXX는 그냥 의미없이 돌아가는 코드가 되는 것

b는 어떻게 a랑 같은 주소값을 가리킬 수 있을까?
a = "java"가 실행될 때 (처음 생성)
자바 가상 머신(JVM)은 힙(Heap) 메모리 안에 있는 String Constant Pool을 먼저 확인합니다.
풀(Pool) 안에 "java"라는 문자열 객체가 있는지 찾습니다.
아직 없으므로, 풀 안에 "java" 객체를 새로 하나 만들고 변수 a에 그 주소값을 담아줍니다.
b = "java"가 실행될 때 (재사용)
똑같이 String Constant Pool을 확인합니다.
이미 아까 a를 만들면서 넣어둔 "java" 객체가 풀 안에 존재하는 것을 확인합니다!
자바는 "어? 똑같은 문자열이 이미 있네? 새로 만들지 말고 저걸 같이 쓰자!" 하면서, 기존에 있던 "java" 객체의 주소값을 변수 b에도 똑같이 담아줍니다.
스트링풀 구조는 해시테이블 -> 검색속도가 빠르지 따라서, 100만개 있따고해서 100만번 뒤지는게아니고 풀에서
거의 비용이 소모되지않는다
GC는 언제 정리해주는거야? concat이나 이런거 엄청 많이했다고 치면?



보통 Heap은 Young 영역(Eden, Survivor0, Survivor 1)과 Old 영역으로 나눈다
-> 객체들은 금방 소환되고 죽는 것들이 많다 그래서 Young 영역만 제때 치워주는 것이 효율적