String 문자열
String은 문자열 리터럴 동일하다면 String 객체 공유
문자열 상수 풀(String Constant Pool)
자바 힙 영역에는 문자열 리터럴을 저장하는 저장 공간
이 저장 공간을 통해서 문자열을 관리한다.
- 문자열 상수 풀에 동일한 문자열("hello")이 이미 존재하는지 확인한다.
- 문자열 상수 풀에 문자열이 있다면, 해당 문자열에 대한 참조를 반환한다.
- 문자열 상수 풀에 문자열이 없다면, 풀에 새로운 문자열을 생성하고 문자열에 대한 참조 값을 반환한다.
new 키워드를 이용하여 String 객체를 생성할 때에는 문자열이 문자열 상수 풀에 저장되지 않습니다.
new 키워드를 사용할 때 JVM은 힙 영역에 새로운 String 객체를 생성합니다.
따라서 메모리 공간 효율(재사용성)을 고려한다면 문자열을 생성할 때
new 키워드보다 문자열 리터럴을 사용하는 것이 더 좋습니다.
상수풀 설명 블로그 : https://hyeran-story.tistory.com/123
String
String은 문자열을 나타내는 클래스입니다.
String 클래스는 연속된 문자(문자열)을 나타내는 클래스입니다. String 객체는 두가지 방법으로 생성할 수 있습니다.
(1) 문자열 리터럴(쌍따옴표로 표현된 문자열)을 이용한 String 객체 생성
public static void main(String[] args) {
String strLiteral1 = "Hello";
String strLiteral2 = "World";
}
(2) new 키워드를 이용한 String 객체 생성
public static void main(String[] args) {
String strUsingNew1 = new String("Hello");
String strUsingNew2 = new String("World");
}
JVM은 문자열 상수 풀을 이용하여 문자열 리터럴을 관리합니다.
자바 힙 영역에는 문자열 상수 풀(String Constant Pool)이라는 문자열 리터럴을 저장하는 저장 공간이 있습니다. JVM(Java Virtual Machine)은 이 공간을 이용하여 메모리 공간을 효율적으로 관리합니다. 우리가 문자열 리터럴을 이용하여 String 객체를 생성할 때 JVM은 다음과 같이 동작합니다.
문자열 상수 풀에 동일한 문자열("hello")이 이미 존재하는지 확인한다.문자열 상수 풀에 문자열이 있다면, 해당 문자열에 대한 참조를 반환한다.문자열 상수 풀에 문자열이 없다면, 풀에 새로운 문자열을 생성하고 문자열에 대한 참조 값을 반환한다.
아래의 코드와 같이 문자열 리터럴을 이용하여 String 객체를 생성한다면 메모리 공간은 그림(fig1)과 같이 표현할 수 있습니다.
public static void main(String[] args) {
String str = "hello";
}
여기서 주의할 점이 있습니다. new 키워드를 이용하여 String 객체를 생성할 때에는 문자열이 문자열 상수 풀에 저장되지 않습니다. new 키워드를 사용할 때 JVM은 힙 영역에 새로운 String 객체를 생성합니다. 따라서 메모리 공간 효율(재사용성)을 고려한다면 문자열을 생성할 때 new 키워드보다 문자열 리터럴을 사용하는 것이 더 좋습니다.
아래는new 키워드를 사용하여 String 객체를 생성하는 코드와 이를 실행했을 때의 메모리 공간 입니다.
public static void main(String[] args) {
String strObj = new String("Hello");
}
String 객체는 변경할 수 없습니다.
String 객체는 한 번 생성되면 그 객체가 나타내는 문자열 값을 바꿀 수 없습니다. 이러한 특성을 "Immutable 하다"라고 표현합니다. 한 번 생성된 String 객체는 변경할 수 없기 때문에 JVM은 상수 풀에 저장된 문자열을 재사용할 수 있습니다. 만약 변경할 수 있다면, 언젠가 수정될 가능성이 있기 때문에 재사용할 수 없습니다. JVM은 이러한 String 객체의 특성을 이용하여 메모리 공간을 효율적으로 관리했던 것입니다.
그런데 종종 + 연산을 이용하여 String 객체가 가리키는 문자열을 수정한 경험이 있지 않나요? 사실은 문자열을 수정할 때마다 문자열 상수 풀에 새로운 문자열이 계속 생성되는 것이었습니다. 이러한 코드는 메모리 공간을 비효율적으로 사용하는 코드입니다!!
public static void main(String[] args) {
String str = "Hello";
str += " World";
str += " !!!!";
}
StringBuilder
StringBuilder는 변경 가능한 문자열을 나타내는 클래스입니다.
StringBuilder는 변경할 수 있는(mutable) 문자열을 나타냅니다.
StringBuilder는 문자열 값을 변경할 수 있는 append(), insert() 메소드를 제공합니다.
StringBuilder를 사용한다면 새로운 객체를 생성지 않고
기존의 StringBuilder 객체를 이용하여 문자열을 수정할 수 있습니다.
문자열 변경이 잦다면, String 보다 StringBuilder를 사용하는 것이 좋습니다.
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("Hello");
stringBuilder.append("World");
stringBuilder.append("!!!!!");
}
StringBuilder는 멀티스레드 환경에서 동기화되지 않습니다.
StringBuilder 클래스는 본래 싱글스레드 환경에서 사용되는 목적으로 설계되었습니다.
따라서 StringBuilder 클래스가 제공하는 메소드는 동기화되지 않습니다.
동기화 여부는 StringBuilder와 StringBuffer의 가장 큰 차이점입니다. 아래에 언급할 StringBuffer 클래스도 변경할 수 있는 문자열을 나타내는 클래스입니다. StringBuffer 클래스는 StringBuilder와 동일한 형태의 메소드를 제공합니다. 하지만 멀티스레드 환경에서 동기화됩니다. 쉽게 말해 StringBuffer는 StringBuilder에 동기화 코드가 추가된 클래스입니다.
그렇다면 StringBuffer가 동기화까지 되니 더 좋겠네요? 상황에 따라 다릅니다. 싱글스레드 환경에서만 사용한다면, StringBuilder를 사용하는 것이 좋습니다. StringBuilder 객체는 동기화 관련 작업을 수행하지 않기 때문에 더 적은 코드로 문자열을 수정할 수 있습니다. 즉, 더 빠르게 동작합니다. 반면, 멀티스레드 환경에서 사용한다면, StringBuffer를 사용하는 것이 적절합니다.
StringBuffer
StringBuffer는 변경 가능한 문자열을 나타내는 클래스입니다.
StringBuffer 클래스는 StringBuilder와 동일하게 변경할 수 있는(mutable) 문자열을 나타내는 클래스입니다.
문자열을 변경하는 메소드 또한 StringBuilder와 동일한 형태로 제공됩니다.
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer("Hello");
stringBuffer.append("World");
stringBuffer.append("!!!!!");
}
StringBuffer는 멀티스레드 환경에서 동기화됩니다.
StringBuffer 클래스의 메소드는 멀티스레드 환경에서 동기화됩니다. 그렇기 때문에 멀티스레드 환경에서는 StringBuilder 보다 StringBuffer를 사용하는 것이 적합합니다.
String Buffer 스트링버퍼
StringBuffer는 문자열을 추가하거나 변경할 때 사용합니다.
1. StringBuffer 의 사용법
StringBuffer stringBuffer = new StringBuffer();
stringBuffer .append("Hello");
stringBuffer .append(" ");
stringBuffer .append(World !);
System.out.println(stringBuffer .toString());
출력 : Hello World !
2. StringBuffer 와 String 의 차이점
위 1번의 코드와 결과만 보면 String 의 문자열 덧셈과 다른 점이 없어 보입니다.
하지만 메모리 관리면에서 String의 문자열 덧셈 보다 StringBuffer가 더 효율적입니다.
위 코드에서 StringBuffer 객체는 단 한번만 생성됩니다.
반면에 String 자료형의 문자열 덧셈 + 연산은 연산이 이루어질 때 마다 새로운 String 객체가 생성됩니다.
(코딩할 때 주의하세요)
String 자료형은 한번 값이 생성되면 그 값을 절대 변경할 수 없습니다. (immutable)
trim과 toUpperCase 등 메소드를 보면 문자열이 변경되는 것이 아니라 또 다른 String 객체를 생성합니다.
StringBuffer는 값을 변경할 수 있습니다. (mutable)
즉 StringBuffer 와 String은 상황에 맞게 사용해야 합니다.
StringBuffer는 String 보다 무겁고 속도가 느립니다. (무겁다 : 메모리 사용량이 더 크다)
3. 결론
내가 문자열 추가 또는 변경 작업이 많을 경우는 StringBuffer를,
내가 문자열 추가 또는 변경 작업이 적을 경우는 String을 사용하는게 좋다고 생각됩니다.
String, StringBuilder, StringBuffer 비교 분석
이렇게 다릅니다.
- String 객체는 변경 가능하나 StringBuilder, StringBuffer 객체는 변경 불가능
- StringBuilder는 멀티스레드 환경에서 동기화되지 않으나 StringBuffer는 동기화 됨
Java에서 String 객체는 한번 값이 할당되면 그 공간은 변하지 않습니다.
하지만 Stringbuilder나 StringBuffer 객체는 한번 값이 할당되더라도
한번 더 다른 값이 할당되면 할당된 공간이 변하는 특성을 갖고 있습니다.
여기서 할당된 공간이 변하지 않는 특성을 불변(Immutable)성이라고 하고,
할당된 공간이 변하는 특성을 가변(mutable)성이라고 합니다.
그러면 다음과 같이 String과 StringBuilder, StringBuffer의 특성의 차이를 정리할 수 있습니다.
String
- 불변성을 갖는다. → Immutable 하다.
StringBuilder, StringBuffer
- 가변성을 갖는다. → mutable 하다.
이렇게 사용하면 좋습니다.
문자열의 변경이 잦은 환경에서는 StringBuilder, StringBuffer를 사용할 것
StringBuffer
멀티스레드 환경을 고려한다면 StringBuffer를 사용할 것
(동기화를 지원하여 멀티 스레드 환경에서도 안전하게 동작할 수 있습니다.)
StringBuilder
싱글스레드 환경에서 StringBuilder를 사용할 것
(동기화를 지원하지 않는 반면, 속도면에선 StringBuffer 보다 성능이 좋습니다.)
스레드 : 프로세스 내부에 있는 CPU 수행 단위
스레드(thread)란 프로세스(process) 내에서 실제로 작업을 수행하는 주체를 의미합니다.
모든 프로세스에는 한 개 이상의 스레드가 존재하여 작업을 수행합니다.
또한, 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스(multi-threaded process)라고 합니다.
프로세스 - 운영체제로부터 자원을 할당받는 작업의 단위이다.
쓰레드 - 프로세스가 할당받은 자원을 이용하는 실행의 단위이고 프로세스 내에 여러개 생길 수 있다.
a처리한 다음에 b처리하고 c처리하는 것 : 비동기식
a b c 동시에 처리하는 것 : 동기식
정리 참고 원본 링크
https://hun-developer.tistory.com/19
이미지 출처 : 이것이자바다
'STUDY > JAVA' 카테고리의 다른 글
[JAVA-이것이자바다.7장] 상속 확인 문제 (0) | 2022.07.18 |
---|---|
[JAVA] 22-07-18 익명 객체 ☑ (0) | 2022.07.18 |
[JAVA] 22-07-14 중첩 클래스 중첩 인터페이스 ☑ (0) | 2022.07.14 |
[JAVA-이것이자바다.6장] 클래스 확인 문제 (0) | 2022.07.13 |
[JAVA-이것이자바다.5장] 참조 타입 확인 문제 (0) | 2022.07.13 |