jeongwon
String 문자열 저장 - new 연산자, 메모리, Heap, String Pool, 불변성 본문
String 타입 변수에 문자열을 저장할 때,
new 연산자 사용 여부에 따라 메모리 상의 다른 영역에 저장된다.
new 연산자를 사용하지 않을 경우 :
String s1 = "Java";
Heap 메모리 내부의 String 상수 영역인 String Constant Pool 에 저장된다.
동일한 문자열의 내용으로 새로운 참조변수를 생성한다고 해도, new 연산자를 사용하지 않으면
참조변수는 Pool 영역 내에 동일한 문자열이 저장된 주소를 가리킨다.
String s2 = "Java";
s2 역시 s1과 동일한 주소를 가리킨다는 의미다.
new 연산자를 사용할 경우 :
String s3 = new String("Java");
String은 사실 클래스이기 때문에 위와 같이 생성이 가능하다.
(혹은 String은 클래스임에도 자주 쓰이는 만큼 간편하게 문자열을 사용할 수 있도록 편의를 제공받는다.)
위와 같이 연산자를 사용할 경우 메모리 상 String Constatn Pool 외부의 새로운 영역에 저장되며,
s3는 s1, s2와는 다른 주소값을 갖는다.
String의 불변성
String s4="java";
s4.replace("j", "J");
System.out.println(s4); //출력 결과: java
System.out.println(System.identityHashCode(s4)); //653687670
s4=s4.replace("j", "J");
System.out.println(s4);//출력 결과: Java
System.out.println(System.identityHashCode(s4)); //356473385
replace() 메소드를 통해 소문자 "j" 를 대문자로 변경했는데, s4의 값에는 영향을 미치지 않았다.
다시 동일한 변수 이름의 s4에 replace() 메소드를 적용한 값을 저장했다.
동일한 변수명에 저장했으니 같은 주소(메모리상 값이 저장된 곳)를 참조할까?
해쉬코드를 반환해주는 System.identityHashCode() 메소드를 통해 출력해본 결과, 전 후의 주소 값은 달랐다.
기존 s4가 참조하는 영역의 실제 문자열 값이 대문자로 시작하는 "Java" 로 변경된 것이 아니라(불변성),
"Java"라는 문자열이 새롭게 다른 영역에 저장되었고, s4가 이제는 그 주소값을 저장하고 있음을 알 수 있다.
(더는 자신을 참조하고 있는 변수가 없는 소문자 "java" 문자열은 이후 가비지 컬렉터에 의해 정리될 것이다.)
String 의 불변성은 '메모리의 낭비'를 초래한다. 이 문제를 해결한 것이 StringBuffer, StringBuilder이다.
https://jeongwon-devlog.tistory.com/8
참고로 replace() 는 위와 같이 String, StringBuffer, StringBuilder 에 공통으로 있지만, String 클래스의 메소드를 자주 사용한다고 함.
String str1 = ""; // '\0'
String str2 = null;
참고로 str1 의 초기화 결과는 주소값을 가지며 실제로 '\0' 라는 값이 저장되는 것이고,
str2의 경우 str2가 참조하는 주소값 자체가 아직 없는 경우다.
이외 몇몇 참고할 만한 메소드들:
String str3 = "hello";
String str4 = str3.concat(" world");
System.out.println(str3.length()); //5
System.out.println(str3.charAt(1)); //e
System.out.println(str4.indexOf("world")); //6 //없으면 -1리턴
System.out.println(str4.substring(0,3)); //hel
System.out.println(str4.toUpperCase()); //HELLO WORLD <-> toLowerCase()
'JAVA' 카테고리의 다른 글
[servlet] javax.servlet.RequestDispatcher (I) (0) | 2022.08.26 |
---|---|
[method] String.getBytes() & charset (0) | 2022.06.04 |
Wrapper class (0) | 2022.05.12 |
StringBuffer, StringBuilder class - 문자열, 메모리, 가변성 (0) | 2022.05.12 |
[1] 클래스, 메소드, 문장, 식별자, 자료형, 변수 (0) | 2022.04.24 |