java, String의 다양한 특징
String는 참조 타입
- String은 int, long, char 등 기본 타입(primitive type)과 달리 참조 타입이다. 동시에 보통의 참조타입과 성격이 다르다. 그러므로 String은 자바를 학습할 때 가장 먼저 배우는 타입이지만 동시에 이해하기 까다로운 타입이기도 하다.
- 기본타입과 참조타입의 차이는 메모리의 저장에 있다. int의 경우 stack에 저장된다. String의 객체는 heap에 저장되며 해당 변수는 heap의 주소를 가리킨다.
- 기본타입과 참조타입의 메모리 저장은 다음과 같은 방식과 같다.
int a = 3;
String b = "java";
변수 | 값 | 주소 | 값 |
---|---|---|---|
int a | 3 | ||
String b | heap 30번지 | heap30번지 | “java” |
- 그러므로 값이 없는 String은 null을 반환하고 int는 0을 반환한다.
String[] strs = new String[3];
System.out.println(strs); // 값 : Ljava.lang.String;@3b6eb2ec
for (String str : strs) {
System.out.println(str); // 값 : null / null / null
}
int[] ints = new int[3];
System.out.println(ints); // 값 : [I@1e643faf
for (int i : ints) {
System.out.println(i); // 값 : 0 / 0 / 0
}
보통의 참조변수와 다른 String의 특징
- 한편, String은 보통의 참조타입가 다른 특징을 가지고 있다.
- 초기화 시 new를 사용하지 않는다.
- 배열의 특징을 가진다.
new를 사용하지 않는다
- 가장 큰 차이는 초기화 방식인데, String은 new를 사용하지 않고 객체를 생성할 수 있다. 다른 두 String 변수에 동일한 문자열을 new 없이 각각 초기화할 경우, 두 개의 변수는 동일한 주소를 가리킨다. 동등성 비교를 할 경우 true를 반환한다.
- new를 통해 초기화 할 경우 동일한 문자열을 가지더라도 변수는 서로 다른 주소를 가리킨다.
LocalDate date = "2021-01-01"; // 컴파일 오류. String 이외에 어떤 객체도 new 없이 초기화할 수 없다. 스태틱 메서드로 생성할 수 있지만 그 내부에는 new를 사용한다.
String a = "java";
String b = "java";
System.out.println(a==b); // true
String aa = new String("spring");
String bb = new String("spring");
System.out.println(aa==bb); // false
String aaa = "aaa";
String bbb = aaa;
System.out.println(aaa==bbb); // true
배열로의 성질
- String은 하나의 문자열이지만 동시에 문자의 조합으로서 동작한다.
- 실제로 String 클래스는 배열로서 사용 가능한 메서드가 존재한다.
- subString(), indexOf(), length, charAt()
String str = "abcdefg";
int length = str.length();
String substring = str.substring(0, 3);
str.charAt(4);
char가 포함하지 못하는 문자를 대신 표현
- char는 65536 개의 문자를 맵핑할 수 있다. 하지만 세상에는 65536 개를 넘는다.
- 우리 입장에서는 특히 한자가 그러하다.
char c1 = '홣';
System.out.println((int) c1); // 54883
System.out.println((char) 54883); // 홣
String s = "𣦝";
System.out.println(s); // 𣦝
char c = s.charAt(0);
System.out.println(c); // ?
- 한자와 같은 경우 char 대신 String을 사용한다.