본문 바로가기
Java

String, StringBuffer 클래스

by 개발자공부 2024. 4. 29.

String 클래스

String 선언하는 두 가지 방법

힙 메모리(heap memory)에 인스턴스로 생성되는 경우 (힙 메모리는 생성될 때마다 다른 주소 값을 가진다.)

상수 풀(constant pool)에 있는 주소를 참조하는 경우 (상수 풀에 문자열은 모두 같은 주소 값을 가진다.)

리터럴 방식으로 한 번 생성된 String은 불변(immutable)이다. 그러나 다른 String을 연결하면 기존의 String에 연결되는 것이 아닌 새로운 문자열이 생성된다. (StringBuffer는 객체 하나를 생성해서 그걸 수정해서 사용한다. String처럼 계속 생성하는 것이 아니다.)

String str1 = "Hello"; // constant pool

String str2 = new String("Hello"); // heap memory
String str3 = new String("Hello"); // heap memory

 

String name1 = new String("abc"); // 객체를 생성했기 때문에 메모리를 소모한다.
String name2 = new String("abc"); // 그렇다면 계속 메모리를 차지할 것인가?
// ---> 메모리 절약을 위해 상수 풀을 사용해야 한다.
System.out.println(name1 == name2); // 주소값이 다르니 false가 출력된다.

String name3 = "abc";
String name4 = "abc"; // 불변
// 상수 풀에 올라간 String 값은 먼저 존재하는지 확인부터 한다.
// 완전 똑같은 문자열 abc가 존재한다면 
// 새로 생성하지 않고 다시 재사용한다. <-- 핵심!
System.out.println(name3 == name4); // 상수 풀에 같은 값이니 true가 출력된다.
// == 는 참조타입에 썼을 경우 객체 주소값을 비교한다.
// equals는 문자열 값을 비교한다.
// 결론적으로 문자열 비교는 논리적인 판단으로 같은지 다른지 true,false값을 반환한다.

System.out.println(name1 == name4); // 하나는 heap, 하나는 constant pool이니 false 출력
System.out.println(name1.equals(name4)); // 문자열이 같으니 true 출력
String str3 = "abc";
String str4 = "abc";

System.out.println(str3); // 주소값이 나와야하는데 toString Override되어 있어서 데이터가 출력된다.
System.out.println(System.identityHashCode(str3)); // 원시 코드로 올라가서 str3의 주소값을 확인해보자.
System.out.println(System.identityHashCode(str4)); // 똑같은 abc 데이터니까 똑같은 주소값이 나온다.

str3 = str3 + "def";
System.out.println(System.identityHashCode(str3));
// 문자열은 더한 다음 원시 코드로 올라가서 str3의 주소값을 확인해보니 기존과 달려졌다.
// 리터럴 타입으로 생성한 String은 한 번 생성하면 불변이다. 
// 즉 str3가 정의한 abc는 사라진게 아니다. abcdef는 새로 상수 풀에 생성되었다.

 

String text block

문자열을 """    """ 사이에 이어서 만들 수 있다. html과 json 문자열을 만드는데 유용하게 사용할 수 있다.

"를 3개 입력하고 enter를 누르면 자동 완성된다.

package useful;

public class StringTextBlock {

	public static void main(String[] args) {
		String strBlock0 = "  " + "aa" + "안녕"; // 여태까지 수업에서 문자열 쓰던 방법

		// """ 찍고 한 줄 내리기
		String strBlock = """
				This
				is
				Text
				block
				test.
				""";

		String a = """
				dddd
				""";

		String htmlText = """
				<!doctype html>
				<html dir="ltr" lang="ko"
				    chrome-refresh-2023>
				  <head>
				    <meta charset="utf-8">
				    <title>새 탭</title>
				    <style>
				      body {
				        background: #FFFFFF;
				        margin: 0;
				      }

				      #backgroundImage {
				        border: none;
				        height: 100%;
				        pointer-events: none;
				        position: fixed;
				        top: 0;
				        visibility: hidden;
				        width: 100%;
				      }

				      [show-background-image] #backgroundImage {
				        visibility: visible;
				      }
				    </style>
				  </head>
				  <body>
				    <iframe id="backgroundImage" src=""></iframe>
				    <ntp-app></ntp-app>
				    <script type="module" src="new_tab_page.js"></script>
				    <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
				    <link rel="stylesheet" href="chrome://theme/colors.css?sets=ui,chrome">
				    <link rel="stylesheet" href="shared_vars.css">
				  </body>
				</html>
								""";
		// html, json 문자열을 만드는데 유용하다

	}

}

 


StringBuffer 클래스

  String 클래스의 잦은 변화가 있을 때 메모리 낭비가 발생할 수 있다는 개념을 알았다면 대체 방법에 대해 살펴보자.

대체 방법으로는 StringBuilder, StringBuffer 활용할 수 있는데 StringBuffer는 멀티 쓰레드(multi thread) 프로그래밍(백엔드 서버)에서 동기화(synchronization)을 보장하기 때문에 StringBuffer만 알아보도록 하자.

package useful;

public class StringBufferTest {

	// 코드의 시작점 - (메인 작업자)
	public static void main(String[] args) {

	// heap memory에 객체 생성
		String str1 = new String("Hello");
		String str2 = new String("World"); 

	// StringBuffer 객체 생성
		StringBuffer bufferStr = new StringBuffer("Hello");
		System.out.println(bufferStr);
		System.out.println(System.identityHashCode(bufferStr)); // 원시 주소 값 확인

	// StringBuffer에 append
		bufferStr.append(str2); // bufferStr 변수에 str2 변수 더하기
		System.out.println(bufferStr);
		System.out.println(System.identityHashCode(bufferStr)); // 같은 주소값이 나오니 새로운 객체가 생성된 건 아니다.
		
		//1번 결과와 2번 결과 주소값이 같다라는 의미는 
		//새로운 메모리를 할당한 것이 아닌 변경한 것이다.
		
		//활용
		String newStr = bufferStr.toString(); // toString 호출시 타입 -> String
		
	} // end of main

} // end of class

 

☞ 내부적으로 가변적인 char[]를 멤버 변수로 가진다.

☞ 문자열을 여러번 연결하거나 변경할 때 사용하면 유용하다.

☞ 새로운 인스턴스를 생성하지 않고 char[]를 변경한다.

☞ StringBuffer는 멀티 쓰레드 프로그래밍에서 동기화를 보장한다.

☞ 단인 쓰레드 프로그램에서는 StringBuilder 사용을 권장한다.

☞ toString() 메서드로 String 반환

'Java' 카테고리의 다른 글

Thread, multi-threading (스레드)  (0) 2024.05.01
Exception(예외처리)  (0) 2024.04.29
Object 클래스  (0) 2024.04.29
Interface (인터페이스)  (0) 2024.04.26
Abstract class (추상 클래스)  (0) 2024.04.26