현업에서 시스템 장애를 진단 작업을 하면서 어떤 객체가 가장 많이 생성되는지 점검 하는 경우 String 관련 객체는 몇백개 객체 중에서 상위 5개 안에 항상 포함된다고 한다. String 클래스에 대해 잘 알아야 하는 이유가 되겠다.
String 은 어떻게 생겼을까?
package java.lang;
public final class String // (1) 자식클래스 양산 불가
implements java.io.Serializable, Comparable<String>, CharSequence,
Constable, ConstantDesc // (2)
- 자식클래스 양산 불가
- 누구나 사용할 수 있는 클래스
- 클래스가 final 로 선언되어 있으므로 더이상 이 클래스를 확장할 수 없다.
- 구현하는 인터페이스 목록
- 인터페이스를 implements 한 클래스는 선언되어 있는 메소드의 몸통을 구현해야만 한다.
Serializable
- 인터페이스는 구현해야 하는 메소드가 없는 특이한 인터페이스다.
⇒ 해당 객체를 파일로 저장하거나 다른 서버에 전송 가능한 상태가 된다.
Comparable
- compareTo() 메소드 하나만 선언되어있다.
- 매개변수로 넘어가는 객체와 현재 객체가 같은지 비교
- 리턴 타입 int
- 0: 같은 값일 때
- -1 : 순서상으로 앞에 있을 때
- 1: 순서 상으로 뒤에 있을 때
- 객체의 순서 처리할 때 유용
CharSequence
- 해당 클래스가 문자열을 다루기 위한 클래스임을 명시적으로 나타냄
- StringBuilder, StringBuffer 도 CharSequence 를 다룬다.
String 선언하기
String 을 선언하는 방식은 크게 두가지가 있다.
하나는 기본 자료형을 선언 하듯이 초기화하는 방법, 다른 하나는 객체를 생성 하듯이 초기화 하는 방법이다.
String str="literal";
String str2 = new String("str object");
두 방식에 대해 자바는 구분하고 있다.
아래와 같은 코드를 실행한다고 생각해보자
public void checkCompare(){
String textA = "Check value";
String textB = "Check value";
if (textA == textB){
System.out.println("textA == textB"); //출력
} else {
System.out.println("textA == textB result is different.");
}
if(textA.equals("Check value")){
System.out.println("textA.equals(textB) result is same"); //출력
}
}
--------------------
[실행결과]
textA == textB
textA.equals(textB) result is same
String literal 로 선언한 두 변수는 각각 같은 값을 갖고 있어 서로 같은 것으로 인지된다.
그렇다면 아래와 같은 경우에도 변함이 없을까?
public void checkCompare(){
String textA = "Check value";
String textC = new String("Check value");
if (textA == textC){
System.out.println("textA == textC");
} else {
System.out.println("textA == textC result is different.");
}
if(textC.equals("Check value")){
System.out.println("textC.equals(textA) result is same");
}
}
---------------------
[실행결과]
textA == textC result is different.
textC.equals(textC) result is same
보기에는 같은 값을 갖고 있어서 결과는 달라지지 않을 것이라 생각하기 쉽다.
하지만 우리의 예상과는 다르게 ‘==’를 이용한 연산에서는 다르게 인식하고 있고, equals 연산에서는 같은 것으로 인식하고 있다.
그 이유는 간단하다.
자바에는 Constant Pool 이 존재하기 때문이다.
Constant Pool
- 객체 재사용을 위한 공간
- String 의 경우 Constant Pool 내부에 동일한 값을 갖는 객체가 있다면 해당 객체를 재사용한다.
- new 를 활용해 String 을 선언하면 새로운 객체를 생성
각 선언 방식에 따른 저장 방식을 표현하면 아래와 같다.

따라서 첫번째 코드에서 literal로 선언한 textA와 textB 객체는 실제로 같은 객체이다.
반면 두번째 코드에서 literal과 객체로 생성한 textA 와 textC 는 서로 다른 객체이다.
String 객체를 생성하면 값이 같은 String 객체를 생성한다고 하더라도 Constant Pool 을 사용하는 것이 아닌 별도의 객체를 생성한다.
이를 통해 또 알 수 있는 점이 있다.
== 로 값을 비교하는 것은 변수의 저장된 주소를 기준으로 비교를 하는 것이고
equals 로 값을 비교하는 것은 해당 object 가 가진 값(대표하는 값)을 기준으로 비교하는 것이다.
그래서 문자열을 비교할 때 equals 메소드를 활용하는 것을 권장한다.
'자바' 카테고리의 다른 글
[Java] static, 잘 알고 사용하자. (0) | 2024.06.03 |
---|---|
[Java] JVM의 이해(3) - Garbage Collection (2) | 2024.02.22 |
[Java] JVM의 이해(2) - 주요 메모리와 static (0) | 2024.02.21 |
[Java] 자바 가상 머신 이해(1) - JVM 구조 (0) | 2024.02.20 |