즉, new 키워드로 새로운 객체를 생성할 수도 있고 & ""안에 값을 입력하여 생성할 수도 있다.
소스상에서 문자열 리터럴은 String 객체로 자동 생성되지만, String 클래스의 다양한 생성자를 이용해서 직접 String 객체를 생성해서 사용할 수도 있다.
public class StringExample {
public static void main(String [] args){
//1. 배열 전체를 String 객체로 생성
String str = new(byte[] bytes);
//2. 배열의 offset 인덱스 위치부터 length만큼 String객체로 생성
String str2 = new String(byte[] bytes, int offset, int length);
}
}
JVM이 관리하는 메모리 구조상에서 명백히 둘은 다르다.
String객체를 생성하는 2가지 방법에 대해서 JVM 메모리상에 어떻게 존재하는지에 대한 그림이다.
리터럴로 생성하면 같은 참조이기에 같은 값을 할당 받지만
new 를 사용하여 생성하면 계속 다르게 생성된다.(메모리 비효율적)
Java의 String은 "특별 참조형" 이다.
new 생성자를 이용해서 인스턴스를 생성한 뒤, heap에서 메모리 관리가 이루어진다.
(이건 다른 참조 자료형과 동일하다.)
But, 다른 참조형과 다르게 변하지 않는다는 특징이 있다.
public class Ex{
public static void main(String[] args){
String ex1 = new String("e");
String ex2 = "e";
String ex3 = "e";
}
}
ex1은 heap 메모리에 개별 객체가 만들어지고,
ex2, ex3는 String Constant Pool에 만들어진 하나의 객체를 참조한다.
즉, 위의 코드로 생성된 String 객체는 2개이다.
String Constant Pool
- String 객체들의 연산이 이뤄지면, 새로운 객체를 계속 만들어내기에 메모리 관리 측면에서 상당히 비효율적이다.
- 이러한 이유로 메모리 영역이 Heap안에 있는 String Constant Pool이 만들어졌다.
- 기존의 문자열 값이 저장되어있고, 리터럴로 생성된 같은 값을 가지는 객체는 같은 참조를 가지게 된다.