본 포스트는 카카오 테크 캠퍼스 1기에서 제공하는 패스트캠퍼스 강의에서 배운 내용을 토대로 정리하였습니다.
힙 메모리에 인스턴스로 생성되는 경우와 상수 풀(constant pool)에 있는 주소를 참조하는 두 가지 방법이 있다.
String str1 = new String("abc"); //인스턴스로 생성
String str2 = "abc"; //상수 풀(constant pool)에 있는 주소를 참조
힙 메모리는 생성될때마다 다른 주소 값을 가지지만, 상수 풀의 문자열은 모두 같은 주소 값을 가짐
public class StringTest {
public static void main(String[] args) {
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1 == str2);//false
System.out.println(System.identityHashCode(str1));//2055281021
System.out.println(System.identityHashCode(str2));//1554547125
//즉 해쉬코드가 다르므로 생성될때 마다 서로 다른 주소를 가짐을 확인 가능.
String str3 = "abc";
String str4 = "abc";
System.out.println(str3 == str4);//true
System.out.println(System.identityHashCode(str3));//617901222
System.out.println(System.identityHashCode(str4)); //617901222
//즉 해쉬코드가 같으므로 상수 풀의 문자열은 모두 같은 주소값을 가짐
}
}
왜그런지 알려면, 상수 풀이 무엇인지 알아야한다.
String literal로 생성한 객체는 "String Constant Pool"에 들어간다.
"String Constant Pool"은 Heap 영역 내 존재한다.
new 연산자로 생성한 String 객체는 같은 값이 String Pool에 이미 존재하더라도, Heap 영역 내 별도의 객체를 가리키게 된다.
즉,
자바에서 String 자료형 변수를 String literal로 생성하면 해당 String 값은 Heap 영역 내 "String Constant Pool"에 저장되어 재사용되지만,
new 연산자로 생성하면 같은 내용이라도 여러 개의 객체가 각각 Heap 영역을 차지한다. => 일반적인 객체의 동적할당 과정과 동일.
String literal로 생성한 객체의 값(위그림에선 "Cat")이 이미 String Pool에 존재한다면, 해당 변수는 String Pool의 메모리 주소를 참조한다.
위 그림에서 변수 s1과 s2가 같은 곳을 가리키고 있는 것도 이 때문이다.
한번 생성된 String은 불변(immutable)하다
String을 연결하면 기존의 String에 연결되는 것이 아닌 새로운 문자열이 생성됨 ( 메모리 낭비가 발생할 수 있다.)
public class StringTest2 {
public static void main(String[] args) {
String java = new String("java");
String android = new String("android");
System.out.println(System.identityHashCode(java));
java = java.concat(android);
System.out.println(System.identityHashCode(java));
//java변수의 해쉬코드와, 거기에 android를 이어붙인 변수의 해쉬코드는 다르다.
}
}
새로운 인스턴스를 생성하지 않고 char[] 를 변경함
StringBuffer는 멀티 쓰레드 프로그래밍에서 동기화(synchronization)을 보장 => 공유자원 동시접근시, 순서가 정해짐
단일 쓰레드 프로그램에서는 StringBuilder 사용을 권장
toString() 메서드로 String반환
public class StringBuilderTest {
//StringBuffer도 문법이 똑같음.
//StringBuffer buffer = new StringBuffer(java);
public static void main(String[] args) {
String java = new String("java");
String android = new String("android");
StringBuilder buffer = new StringBuilder(java);
System.out.println(System.identityHashCode(buffer));
buffer.append("android");
System.out.println(System.identityHashCode(buffer));
//출력한 두 해쉬코드는 동일한 16진수를 출력함
java = buffer.toString();
}
}
Java 15부터는 """ (큰따옴표 3개)로 시작하여 그 뒤에 선택적 공백과 줄 바꿈이 오는 텍스트 블록을 사용할 수 있다.
html, json 문자열을 만드는데 유용하게 사용할 수 있음
public class StringTextBlock {
public static void main(String[] args) {
String strBlock = """
This
is
text
block
test.""";
System.out.println(strBlock);
System.out.println(getBlockOfHtml());
}
public static String getBlockOfHtml() {
return """
<html>
<body>
<span>example text</span>
</body>
</html>""";
}
}