문자열(String) Class 사용법

2021. 8. 9. 22:39Java/Etc

 

문자열?? 그냥 사용하면 되는 거 아닌가 하지만 Java에서 가장 많이 가장 쉽게 사용하는 게 바로 이 문자열(String)이다.

그렇기 때문에 해당 문자열에 대해서 사용법을 조금 더 알고 있다면 좋은 성능을 발휘(?) 할 수 있지 않을까 한다.

 

String의 Life Cycle

String은 가장 쉽게 접할 수 있는 불변(Immutable) 클래스의 하나이다.

문자열 생성 시 별도의 String Pool에 생성어 되어 Immutable 하게 관리되는데 빈번하게 사용되기 때문에 같은 문자열에 대해서는 하나의 참조 값을 가지고 재사용되도록 하여 메모리를 효율적으로 관리한 것이다.

이러한 특징이 존재하는 String은 문자열을 사용함에 있어서 연산 등 문자열이 변경되는 경우 기존 정보에 추가되는 것이 아니라 새로운 문자열 객체를 만들고 그 객체를 참조하도록 하는 것이다.

그렇게 되면 기존 문자열 객체는 참조가 사라지게 되고 해당 객체는 GC(Gabage Collection)으로 인해 초기화된다.

for(int i=0; i<10; i++){
	//String Pool에 등록된 Immutable한 String
	String str = "Immutable String"; 
	//항상 같은 참조값을 가짐
	System.out.println(System.identityHashCode(str));
    
	//연산을 통해 매번 새롭게 생성되는 String
	String strNew   = str + "" + i;
	//이전의 값은 GC의 대상이 되며 새로운 참조값으로 생성됨
	System.out.println(System.identityHashCode(strNew));  
}

물론 모든 String이 이러한 것은 아니며 초기화에 따라 다른 방식이 존재하기도 하는데 자세한 String의 특징은 해당 내용은 아래 내용을 참고해 보면 된다.

 

About String Class

우리는 String 하면 문자열을 표현하는 데이터 타입(DataType)의 하나로 알고 간단하게 쓰고 있지만 String Class에는 다른 데이터 타입(Primitive Data Type)과는 다른 몇 가지의 특별한(?) 특징이 존재한다.

lovelettee01.tistory.com

 

Immutable 한 String의 연산

위에서 설명한 String의 불변적 특징이 과연 메모리를 효율적으로 관리할 수 있을까??

기존 객체를 계속 사용하게 되면 상관이 없지만 기존 객체가 연산을 통해 새로운 객체를 생성하게 되면 매번 새로운 객체가 생성되기 때문에 메모리를 비효율적으로 사용하게 된다.
Immutable 한 String의 특징은 메모리의 효율적 관리를 위해 구현되었지만 사용함에 있어 불필요한 메모리의 낭비를 불러오게 되는 것이다.
Java 컴파일러의 발전으로 인해 최적화되고는 있지만, 이러한 비효율적인 메모리의 사용을 피하기 위하여 String에서는 두 가지 클래스를 제공한다.

 

StringBuffer, StringBuilder Class의 활용

String의 불변(Immutable) 한 특징과 반대로 StringBuffer, StringBuilder는 가변(mutable) 적인 특성을 가지고 있다.

두 클래스는 mutable 한 가변적 특성 때문에 객체 생성 이후 동일한 객체 내에서 문자열의 추가(append), 수정(insert), 삭제(delete)가 이루어지기 때문에 문자열의 연산이 빈번하게 일어나는 경우라면 StringBuffer 또는 StringBuilder 클래스를 사용하는 것이 더 효율적이다.

 

위에서 사용한 소스를 가지고 확인해보면 새로운 문자열이 추가되어도 항상 같은 참조 값을 가지는 걸 확인해볼 수 있다.

StringBuffer sb = new StringBuffer(); 	//or StringBuilder sb = new StringBuider();
for(int i=0; i<10; i++){
    String str = "Immutable String"; 	//String Pool에 등록된 Immutable한 String
    System.out.println(System.identityHashCode(str));     //항상 같은 참조값을 가짐
    
    sb.append(str + "" + i);  		// append함수를 이용하여 문자열 추가
    System.out.println(System.identityHashCode(sb));      //항상 같은 참조값으로 생성됨
}

 

!!! 주의사항

하지만 위 방식에는 약간의 문제가 존재한다.

StringBuffer 나 StringBuilder를 사용하여 하나의 객체를 사용하여 문자열의 연산 작업을 하고 있지만 해당 클래스의 함수로 전달돼 오는 (str + "" + i) 해당 부분은 String 문자열의 immutable 한 연산이 이루어지고 있다.

 

실제로 많이 범하는 오류로서 객체 자체는 StringBuffer 또는 StringBuilder를 사용하고 있지만 해당 클래스 안에서 사용하는 문자열 인자에서 +연산이 이루어진다면 실제로 가변 클래스를 사용하는 방식이 무의미해지는 경우가 발생한다.

StringBuffer sb = new StringBuffer(); 	//or StringBuilder sb = new StringBuider();
for(int i=0; i<10; i++){
    String str = "Immutable String"; 	//String Pool에 등록된 Immutable한 String
    System.out.println(System.identityHashCode(str));     //항상 같은 참조값을 가짐
    
    sb.append(str).append(i);  		// append함수를 이용하여 문자열 추가
    System.out.println(System.identityHashCode(sb));      //항상 같은 참조값으로 생성됨
}

위 소스처럼 가변 클래스인 StringBuffer / StringBuilder를 사용하기 위해서는 API메서드를 통한 문자열 변경을 하여야 하며 + 연산 사용에 주의하며 사용해야 한다.

 

StringBuffer, StringBuilder Class의 차이

실제로 두 클래스는 상속받는 클래스 및 Interface에는 차이가 없으며 동일한 API를 가지고 있다.

그럼에도 두 개를 나눠놓은 이유는 동기화(syncronized) 유무로서 멀티 스레드 환경에서 안정성(Thread-safe) 차이가 난다.

  • StringBuffer : 멀티 스레드 환경에서의 안전하다 (Thread-safe)
  • StringBuilder : 멀티 스레드 환경에서의 안전하지 않다.

즉, 멀티 스레드 환경에서는 안정성을 보장하는 StringBuffer를 사용하는 게 안전하다.
반대로 단일 스레드 환경이라면 StringBuffer보다는 StringBuilder를 사용하는 것이 성능 면에서 더 뛰어 나다.

 

마치며..

문자열의 클래스의 사용은 최적화의 문제이지 개발 방법의 문제는 아닐 수도 있다.
점점 서버의 성능이 좋아지고 최적화가 잘 됨에 따라 신경 쓰지 않아도 될 부분일 수도 있지만 규모가 커지고 사용량이 많아지게 되면 혹시 모르게 발생할지 모를 문제점에 대해서 미리 방지하도록 구현하는 것이 최선의 선택일 수도 있다.

 

문자열을 사용하는 String 클래스들의 특징을 간단하게 정리하자면 아래와 같을 것이다.
문자열의 사용방법과 최적화 등등에 따라서 속도 및 메모리 사용량은 차이가 날 수밖에 없으니 각각의 상황에 맞게 적절히 사용하면 될 것 같다.

 

< String, StringBuffer, StringBuilder 간단 요약 >

  String StringBuffer StringBuilder
사용환경 연산이 적은 멀티스레드 연산이 많은 멀티스레드 연산이 많은 단일스레드
불변여부 불변(Immutable) 가변(mutable) 가변(mutable)
스레드안정성(Thread-safe) 안전함 안전함 안전하지 않음
수행속도 빠름 상대적 느림 빠름

 

'Java > Etc' 카테고리의 다른 글

불변 객체(Immutable Object)  (0) 2021.06.04
About String Class  (0) 2021.05.22
프로그램에서 음수 표현 방식  (0) 2021.05.14