자바를 처음 배울 때 "문자열 비교는 무조건 equals 를 사용해야 한다" 라고 배우기 때문에 왜 equals 를 사용해야 하는지 모르고 넘어가는 것 같다 아니, 왜 그럴까 생각 하는 사람들이 많지 않은 것 같다. 나 역시도 그랬고, 당연히 equals 를 사용해야 한다고 알고 있다. 근데 이런 단편적인 지식은 자바를 처음 배우는 사람들도 당연히 아는 지식이고, 결국 경력자임에도 불구하고 나는 자바를 처음 배우는 사람과 크게 다른 점이 없다는 생각이 들었다.
class A {
String a = "abc";
String b = "abc";
}
위와 같은 클래스가 있다고 가정하자.
개발자분들에게
if(a == b) {
System.out.println("같다")
} else {
System.out.println("다르다")
}
결과를 예상하라고 하면,
자바에 관삼이 있으신 분들은 "같다"라고 말할 것이고, equals 를 사용해야한다고 처음에 배웠던 분들은 String 은 reference 클래스니까 "다르다" 라고 결과를 예상할 수 도 있을 것 같다.
여기서 같다, 다르다 를 선택한 결과는 별로 중요하지 않다.
결과에 이르기 까지의 생각이 매우 중요한데,
첫번째 결과가 같다 라고 말씀 하신 분들은 (문자열 리터럴은 String Pool 에 HashMap 으로 저장되고 관리되니까 당연히 같지! 라고 JVM 스펙 차원에서 말할 수 있지만 이러한 프로세스를 몰랐다면?)
class A {
String temp = new String("abc");
String a = temp;
String b = temp;
}
컴파일러가 이런식으로 해석한다고 생각했던 것이고,
후자는
class A {
String a = new String("abc");
String b = new String("abc");
}
컴파일러가 위와같이 해석한다고 결과가 "다르다"가 출력된다고 생각했던 것이 아닐까 ?
일단 답은
컴파일러의 입장에서 생각해보면, String 클래스는 기본적으로 Immutable(값이 변경될 수 없는) 의 성격을 가지고 있기 때문에, 매번 객체를 새로 만들어내야하는데, 이를 비효율적이라고 생각했고, 문자열 리터럴에 대해서만 특별하게 interning 이 가능하도록 했다
이부분을 고려해보면, 위에서 생각했던 방법인 아래 코드가 문제가 있다는 것을 알 수 있다.
class A {
String temp = new String("abc");
String a = temp;
String b = temp;
}
temp 라는 임시 객체를 만들고 있기 때문이다. 따라서 조금더 생각해보면,
class A {
static String a = "abc"
static String b = "abc"
}
이런 모습이 되어야 비로소 a 와 b 를 비교할 수 있을 것 같다.
또 궁금한 점들이 연이어 생긴다.
그럼 class A 가 아니라 class B 에도 같은 방식으로 코딩하고,
A.a == B.a 는 같을까?
같다면 클래스 레벨이 아니라 패키지 레벨 이면 결과는 어떨까? 더 나아가 프로젝트 레벨이면 어떨까?
다른 Jar 파일을 임포트 해서 비교하게 되면 어떨까?
이런 생각들과 끊임 없는 추론을 통해 결과를 예상하고, 실제로 답과 비교해보면서 좀 더 성숙한 개발자가 될 수 있지 않을까 싶다.
아! 물론 정답은
중간에 이야기했지만
class A {
String a = "abc" // new String("abc").intern()
String b = "abc" // new String("abc").intern()
}
컴파일러는 "abc" 라고 문자열 리터럴을 선언하면 주석처럼 해석되며, 내부적으로 String constant pool 을 조회해서 추가되어 있지 않으면 추가하고, 추가되어 있으면 값을 가져온다.
String constant pool 은 어플리케이션에 하나만 존재하기 떄문에 결과적으로 하나의 프로젝트 안에 있는 공통 문자열 리터럴들은 String Pool 에 하나만 존재하게 된다.
'Kotlin & Java' 카테고리의 다른 글
중첩 클래스 와 내부 클래스 (부제 : ViewHolder 를 이너 클래스로 만들때는 왜 static class 로 만들까?) (0) | 2020.03.01 |
---|---|
자주 사용하는 String 클래스 함수 (0) | 2020.02.29 |
자바 기본 타입 (Primitive type) (0) | 2020.02.27 |
간단하게 코루틴 알아보기 (0) | 2020.02.16 |
무공변성 공변성 반공변성 (0) | 2020.01.24 |