해결된 질문
작성
·
113
0
해당 강좌에서
String str1 = "java"로 선언한 객체와
String str2 = new String("java")로 선언한 객체는,
다른 메모리 공간에 저장된다고 말씀하셨는데요.
hashCode()로 확인한 결과 동일한 값이 출력되어 문의드립니다.
String str1 = "java";
String str2 = "java";
String str3 = new String("java");
String str4 = new String("java");
위 코드처럼 선언한 후 hashCode()로 출력하면 str1 ~ str4까지 동일한 값이 출력됩니다.
System.out.println("str1 : str2 -> " + str1.hashCode() + " : " + str2.hashCode());
System.out.println("str3 : str4 -> " + str3.hashCode() + " : " + str4.hashCode());
헌데 동일성 확인을 하면
str1과 str2 는 true 이고,
str3과 str4는 false가 출력되고요.
물론 str1과 str3도 false가 출력됩니다.
이걸 어떻게 해석해야 하는지 문의 드립니다.
답변 2
0
이와 관련한 자세한 내용은 JVM이 문자열 상수를 어떻게 관리하는지 알면 자연스럽게 해결될 것입니다.
[JVM이 문자열 상수를 관리하는 구조]
https://www.inflearn.com/courses/lecture?courseId=335471&unitId=254126&subtitleLanguage=ko
영상에 앞서 짧게 설명해드리면
문자열 상수는 String 객체로 관리되며 JVM 내부 String constant pool을 이용해 별도로 관리합니다. 이는 프로그램 내부에서 같은 문자열 상수가 여러 번 등장하더라도 한 객체로 처리해 효율을 높이기 위한 것입니다.
해시코드 결과가 같다는 것은 같은 인스턴스라는 의미입니다. 그러므로 결국 참조자가 str1~4까지 총 넷 이지만 이들이 최종적으로 참조하는 String 클래스 인스턴스는 결국 한 개라는 것입니다. 참고하시기 바랍니다. 😄
참조자 str1이 가리키는 String 클래스 인스턴스는 이 때 String constant pool에 등록됩니다. str2는 이미 생성된 객체를 참조하게 됩니다. 즉 str1과 str2는 같은 대상에 대한 참조값을 갖게 됩니다. str1 == str2는 단순히 생각해 참조값 그 차체가 같은 것인지 확인하는 연산이라 보면 되겠습니다.
모든 인스턴스를 참조할 수 있는 방법은 결과적으로 메모리 주소값 같은 것일 텐데 Java에서는 주소로 식별이 불가하므로 Object ID값을 사용합니다. Java의 참조자는 C언어의 포인터와 거의 같습니다. C언어의 포인터에 대해 공부해보고 str1, str2 라는 참조가가 C언어의 포인터와 같다고 생각해보시기 바랍니다. 그러면 쉽게 이해 할 수 있으리라 생각합니다. 😄
str1, str2(자료형 간의 비교)의 동일성 비교와
str3, str4(객체 간의 비교)의 동일성 비교를 자바에서 다르게 처리한다는 것으로 이해했습니다.
그렇기에 객체 간의 비교 시에는 가리키는 참조값이 같아도 동일성 결과가 'false'가 출력된다고 이해했습니다.
답변 감사합니다.
0
안녕하세요, 인프런 AI 인턴입니다. 전종락님, 강의와 관련된 질문에 대해 설명드리겠습니다.
자바에서 문자열 비교와 hashCode()
사용
hashCode()
의 동작 원리:
hashCode()
메서드는 객체의 메모리 주소 대신 객체의 내용을 기반으로 해시 코드를 반환합니다. 따라서 동일한 문자열 내용을 가지고 있다면, 그 객체들은 동일한 해시 값을 가질 수 있습니다.str1
, str2
, str3
, str4
모두 같은 문자열 값을 가지므로 이들의 hashCode()
값이 동일하게 출력된 것입니다.동일성과 동등성:
==
)은 두 객체가 동일한 객체인지 확인하는 것이며, 메모리 주소를 비교합니다. 때문에 new String("java")
로 생성된 str3
와 str4
는 다른 메모리 공간에 저장되므로 false
를 반환하게 됩니다.equals()
) 메서드는 두 문자열의 내용을 비교합니다. 만약 str1.equals(str3)
를 사용하면 true
를 반환할 것입니다.문자열 리터럴과 new
키워드:
String str1 = "java"
)은 JVM의 String Constant Pool에서 관리되어 같은 값이 사용될 경우 동일한 주소를 참조하지만,new String("java")
는 항상 힙 메모리에 새로운 객체를 생성합니다. 따라서 메모리 주소가 달라 ==
연산 결과가 false
가 됩니다.질문에서 제기된 hashCode()
에 대한 부분은 동등성을 확인하기 위한 도구로 이해할 수 있습니다만, 동일성을 검증하는 것과는 다른 메커니즘임을 알고 계시면 좋습니다.
추가적으로 참고할 수 있는 강좌의 유사한 질문과 답변을 추천드립니다:
- Java에서 동일성과 동등성의 차이 이해하기
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
hashCode()
메서드는 객체의 메모리 주소 대신 객체의 내용을 기반으로 해시 코드를 반환합니다. 따라서 동일한 문자열 내용을 가지고 있다면, 그 객체들은 동일한 해시 값을 가질 수 있습니다.
이 말은 String 객체에 한해서만 적용되는 말인가요?
class Test {
public String string = "test";
}
Test test1 = new Test();
Test test2 = new Test();
System.out.println(test1.hashCode() + " " + test2.hashCode());
이 Test 인스턴스의 hashCode()는 다르게 표시가 되네요.
답변 감사합니다.
제가 잘못 이해한 부분은,
"hashCode() 메서드의 결과값이 JVM에 의해 생성된 참조자 자체의 주소값(식별값)이다" 라는 가정 아래,
각 String 객체(str1 ~ str4)의 해시값이 동일하게 나오니,
동일한 해시값을 갖는데, 왜 동일성의 결과가 false로 출력되는가?
즉, 해시값 == 참조자를 식별하는 값 == 참조자 자체의 값
위처럼 이해한 결과인 듯합니다.
그래서 강사님 답변에 대해 제가 이해한 결론은,
hashCode()의 결과값은 각 String 객체(str1 ~ str4)가 가리키는 해시값 이므로
hashCode()의 결과값은 문자열 저장소(SCP)에 저장된 동일한 값을 가리키기에 해시값이 동일하다는 것
때문에 hashCode()의 결과값은 같을 수 있다.
but, 동일성('==')은 인스턴스 자체의 동일성(가리키는 값 뿐만 아니라 인스턴스 자체)를 확인하므로 new로 생성된 객체의 동일성은 false가 출력된다.
헌데, 이렇게 이해하면 해당 예제의 s1과 s2의 동일성에서 true가 나오는 것은 이해하기 어렵네요.
s1과 s2도 처음엔 다르게 생성된 객체일텐요.
s1과 s2는 기본 자료형식(primitive)의 특성을 갖기에 true로 나온 건지 싶네요.
혹시나 잘못 이해한 점이 있다면 조언 부탁 드립니다.