String 클래스 내부로는 사실 char[] 배열로 보관하고 있다.
(📌 자바 9 이후에는 byte[]로 보관한다)String 클래스는 개발자가 직접 다루기 불편한
char[] 을 내부에 감추고
, String 클래스를 사용하는 개발자가 편리하게문자열을 다룰 수 있도록 다양한 기능을 제공
한다.
String a = "hello"; //x001
String b = "java"; //x002
String result1 = a.concat(b);
String result2 = a + b;
System.out.println(result1); //hellojava
System.out.println(result2); //hellojava
String 클래스는 참조형이기 때문에 +연산자는 원래 불가하다. (concat() 과 같은 메서드로만 허용해야함)
하지만 자주쓰이는 문자열의 특성상, + 연산자를 허용해준다.
- 동일성 : 두 객체가
같은 참조값(인스턴스)
을 가리키고 있는지 확인하는 비교법 ( == 연산자 )- 동등성 : 두 객체가 다른 인스턴스라도,
논리적으로 같은 객체
인지 확인하는 비교법 ( equals() 메서드 )
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println("new String() == 비교 " + (str1 == str2)); // false
System.out.println("new String() equals 비교 " + (str1.equals(str2)));
String 클래스는 new로 생성할 때 마다 다른 인스턴스라는 것을 기억한다면, 아래와 같은 코드에 의문이 생길 것이다.
String str3 = "hello";
String str4 = "hello";
System.out.println("리터럴 == 비교 : " + (str3 == str4)); // true (네?????)
System.out.println("리터럴 equals 비교 : " + (str3.equals(str4))); //true
엥? str3==str3 가 true 라고?
이런 의문이 들었다면, String 클래스의 개념이 잘 잡힌 것이다. 서로 다른 인스턴스로 생성되는 것이 분명한데 왜 true가 나올까?
이때, 문자열 pool이라는 개념이 등장한다.
📌리터럴로 문자열이 생성되면, 같은 문자열을 가진 객체들은 하나의 주솟값을 가리키게 된다!
아래 메모리 주솟값을 한 번 출력해보자.
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println("new String() == 비교 " + (str1 == str2)); // false
System.out.println("new String() equals 비교 " + (str1.equals(str2))); //true
String str3 = "hello";
String str4 = "hello";
System.out.println("리터럴 == 비교 : " + (str3 == str4)); // true (네?????)
System.out.println("리터럴 equals 비교 : " + (str3.equals(str4))); //true
System.out.println(System.identityHashCode(str1)); //1989780873
System.out.println(System.identityHashCode(str2)); //1480010240
System.out.println(System.identityHashCode(str3)); //81628611
System.out.println(System.identityHashCode(str4)); //81628611
이와같이 new로 생성했을 때에는, 다른 인스턴스로 메모리에 생성되지만, 리터럴로 생성했을 때에는 문자열 풀에 의해서 같은 인스턴스
를 가리키게 된다.
노노! 그런걱정은 하지않아도 된다!
왜?
String 클래스는불변 객체
이기 때문이다.
값을 변동하고 싶으면 모두 새로운 객체로 생성해서 반환시킨다.
- Null을 가질 수 있다.
- 불변이다.
- 값을 비교할 때는 equals()로 비교해야 한다.
- AutoBoxing - AutoUnboxing 기능을 제공한다.
📌내부 연산 10000번 줄이는 것 보다, 네트워크 호출 1번 줄이는 것이 훨씬 성능이 높아진다.
Class 클래스를 사용
하면 클래스의 메타 정보를 기반으로 클래스에 정의된 메서드, 필드, 생성자 등을 조회하고 이들을 통해 객체 인스턴스를 생성하거나 메서드를 호출하는 작업을 할 수 있다. 이런 작업을리플렉션
이라고 한다.
-> 아마 Spring, Mock?에서 많이 쓰이는 것 같다.