2022. 9. 2. 21:19ㆍ일문일답/Java
Java String
String str1 = new String("Hello"); // new 연산자를 통한 객체 생성
String str2 = "Hello"; // 리터럴 형태로 바로 할당
Java에서 문자열 타입의 특징은 참조 타입임에도 불구하고 직접 new 연산자를 통해 객체를 생성하는 방법이 아닌, 문자열 리터럴 형태로 사용하는 것이 허용된다는 점이다.
String의 불변성(Immutable)
String 객체는 최초 한 번 생성되면 절대로 그 값이 변하지 않는다.
String str = "최초 문자열";
str = "변경된 문자열";
str 이라는 String 객체가 생성된 이후 "최초 문자열" 을 "변경된 문자열" 로 바꾼다고 해도 실제 내부적으로는 최초 생성된 String 객체의 값이 변경되는 것이 아니라 새로운 String 객체가 생성되어 그 참조가 str 변수에 할당된 것이다.
즉, 이 상태에서는 최초에 생성된 "최초 문자열" 과 "변경된 문자열" 두 개의 인스턴스가 Heap 영역에 저장되어 있는 상태인 것이다.
(이후, 참조되지 않는 최초 문자열은 Garbage Collection을 통해 제거된다.)
String 객체가 불변 객체(Immutable)인 이유
1. String 객체의 캐싱 기능
String이 불변의 객체로 생성된 이유는 메모리 절약을 위한 캐싱 기능을 위해서이다.
Java 디자이너는 모든 종류의 Java 애플리케이션에서 가장 많이 사용되는 데이터 타입이 String이 될 것이라고 예측하였고, 따라서 최적화의 필요성을 고려하게 되었다.
그리하여 선택된 방법이 String pool에 리터럴을 포함하여 String 객체를 포함하고, temporary하게 생성된 String 객체를 줄여주는 방식이다.
이 때, 두 영역에서 mutable한 객체는 공유가 불가능하기 때문에 String 객체를 공유하기 위해 String class는 Immutable class가 되어야 한다.
for (int i = 0; i < 500; ++i) {
String str = "Hello World";
System.out.println(str);
}
위와 같은 코드에서 String의 불변성이 없다면 String pool을 통한 String 객체를 공유할 수 없게 되고, 해당 코드는 "Hello World"의 String 객체 500개를 생성하여야 한다.
하지만 불변의 성질을 갖기 때문에 실제로 해당 문자열 객체는 Heap 영역에 단 하나만 생성되어 공유된다.
(이 때, 참조 변수인 str 변수 자체는 각 반복문이 돌 때마다 스택상에 생성되었다가 사라지게 된다.)
그리고, String 객체의 캐싱 기능은 메모리 절약이라는 이점 이외에도 속도의 향상 효과도 수반된다.
Java에서 String 객체들은 Heap의 String pool이라는 특별한 공간에 저장된다.
위의 코드처럼 참조하려는 문자열 "Hello World"가 String pool에 존재하는 경우 새로 생성하지 않고 pool에 있는 객체를 사용한다. 따라서 객체가 새로 생성되는 동작이 필요 없어지므로 성능이 향상된다.
2. 보안상의 이유
String은 다수의 Java 클래스에 매개 변수로 널리 사용되고 있으며, 네트워크를 연결할 때 호스트 및 포트가 String으로 되어있고, Java에서 파일을 읽어 들이기 위한 파일이나 디렉토리 경로도 String으로 되어있으며, 데이터베이스 연결에 필요한 URL도 역시 String으로 되어있다.
이 상황에서 만약 String이 immutable 하지 않다면, 사용자는 시스템의 특정 파일에 대한 엑세스 권한을 얻은 후 Path의 변경이 가능하게 되며, 이렇게 되었을 경우 심각한 보안 문제가 발생할 수 있다.
class loading mechanism에서 자주 사용되는 것도 이유 중 하나이다. String 객체의 값이 변할 수 있다면 java.io.Reader 등 Java 표준 클래스의 로드 요청 시 악성 com.unknown.DataStolenReader 클래스로 변경하게 할 수 있다.
String을 final으로 지정함으로써 JVM은 올바른 클래스들을 로드할 수 있게 된다.
3. Hash
또한 문자열은 HashMap, Hashtable 같은 해시 기반 컬렉션의 키로써 많이 사용되기 때문에 동일한 값으로 저장된 객체의 value를 검색할 수 있도록 immutable한 것이 중요하다. 키로 지정된 문자열의 내용이 수정된 경우 삽입 및 검색 시 두 개의 다른 해시 코드를 생성하여 잠재적으로 맵에서 값 객체를 잃게 된다.
* 혼동하지 말아야 할 개념
- 불면성의 개념, 문자열을 재할당할 때 해당 문자열을 참조하는 객체를 수정하는 것이 아니라 새 문자열을 만들고, 변경된 문자열을 할당한다는 것.
(즉, String은 한 번 생성되면 변경할 수 없으며, 대신 새로운 String 객체가 생성된다.) - 문자열이 변경 불가능하다는 것은 객체 자체는 변경할 수 없지만 객체에 대한 참조는 변경할 수 있다는 의미이다.
[출처]
https://wildeveloperetrain.tistory.com/34
String class가 final인 이유, String의 불변성 (Immutable)
Java의 final에 대해 공부하면서 String class가 대표적인 final class라는 것을 알게 되었고, String class가 final으로 정의된 이유가 궁금하여 찾아보게 되었습니다. Java String String str1 = new String("H..
wildeveloperetrain.tistory.com
'일문일답 > Java' 카테고리의 다른 글
[일문일답][Java] String vs StringBuilder vs StringBuffer (1) | 2022.10.30 |
---|---|
[일문일답][Java] atomic type과 CAS (0) | 2022.10.29 |
[일문일답][Java] Fail Fast, Fail Safe Iterator (0) | 2022.08.25 |
[일문일답][Java] Iterator 인터페이스와 Iterable 인터페이스 (0) | 2022.08.25 |
[일문일답][Java] Reflection의 개념 및 사용 방법 (0) | 2022.08.24 |