자바에서 string 을 사용할 때 , new 를 사용하지 않아도 작동한다는 특징이 있다.
그렇다면 new를 사용한 코드와 그렇지 않은 코드는 어떠한 차이가 있을까?
public class StringPractice {
public static void main(String[] args) {
String str1 = "hello";
String str2 = new String("hello");
String str3 = "hello";
// change into Capital letter
System.out.println(str1.toUpperCase());
//print the 'hello' the original letter
System.out.println(str1);
//change the str1 hello -> hello!!
str1=str1.concat("!!");
System.out.println(str1);
//change hello
System.out.println(str2.substring(1,3));
}
}

new 를 사용하지 않고 코드를 작성하면 주소를 가리키게 된다.
더 자세하게 이야기 해보자면,
String str1 = "hello";
String str2 = "hello";
str1 을 이용해서 hello 를 만들었다.
str1은 hello 를 저장해서 담고있는 것이 아닌, hello 의 주소로 가리키고 있는 것이다.
그래서 str3 가 hello 를 새로 만들기 전에 상수영역에 이미 만들어진 hello가 있는지 확인한다.
확인 후에 str1 이 만들어 둔 hello가 있기 때문에 새로 만들지 않고 str1이 가리키고 있는 같은 hello의 주소를 담고 가리킨다.
첫 번째 출력에서는 toUpperCase() 를 이용해서 HELLO 라는 대문자로 바뀐 결과가 나왔지만,
str1을 다시 출력해봤을때는 대문자로 바뀐 결과가 나오지 않고 처음 저장된 hello가 그대로 나오게 된다.
만약 str1을 변형한 채로 저장하고 싶다면 str1이 가리키는 주소를 다시 바꿔주어야 한다.
즉, str1의 정의를 다시 해주어야한다.
str1=str1.concat("!!");
위의 코드처럼 해준다면 str1은 hello를 참조하는 것이 아닌 hello!! 를 참조하게 된다.
new 를 이용하면 뜻 그대로 heap 영역에 새로운 hello를 만들어준다.
String str1 = new String("hello");
String str2 = new String("hello");
이 둘은 각자 서로 다른 hello를 가리키고 있다.
위의 str은 같은 hello를 가리키고 있고,
new 를 쓰면 각자 다른 영역, 다른 주소의 hello 를 가리킨다.