저번에 풀었던 [백준 1991] 트리순회 문제를 풀면서 궁금증이 생겼다.
BufferedReader로 받아온 String을 char 자료형으로 변환하는 것이 귀찮아서 Node 클래스의 name 필드 자료형을 String으로 지정하여 풀었는데,
static void addNode(Node node, String head, String left, String right) {
if(node.name==head) {
node.left = (left=="." ? null : new Node(left, null, null));
node.right = (right=="." ? null : new Node(right, null, null));
}
else {
if(node.left!=null) addNode(node.left, head, left, right);
if(node.right!=null) addNode(node.right, head, left, right);
}
}
부분에서 에러가 발생했다.
문제가 된 부분은 if (node.name==head) 였다.
해당 부분을 if (node.name.equals(head)) 로 수정하니 해결되었다.
String 객체를 비교할 때 == 보다는 .equals() 의 사용을 권장하는 것은 알고 있었지만, 그 이유에 대해서는 몰랐었기에 궁금하다고 느낀 겸 알아보기로 했다.
== 와 .equals() 의 차이
먼저 짚고 넘어가야 할 몇 가지가 있다.
1. String은 클래스이다
기본 타입(int, char, …) 자료형들은 Call By Value (값에 의한 호출) 형태로 사용된다.
반면 String 같은 클래스는 Call By Reference (참조에 의한 호출) 형태로 사용된다.
2. 문자열 생성 방식에 따른 종류
- 리터럴 방식 (프로그램에서 직접 표현한 값)
String string1 = "literal";
String string2 = "literal";
리터럴 방식으로 String을 만들 경우 String Constant Pool 영역에 배치된다.
더 자세히 설명하자면 내부적으로 먼저 String의 intern 메서드가 선언되어 String Constant Pool 영역에 해당 String 객체가 존재하는지 알아본 후에 존재한다면 그 주소를 반환하고 없다면 Pool에 넣고 그 새로운 주소값을 반환한다. 값/데이터마다 각자의 주소를 할당받는다고 정리할 수 있다.
즉, 위 코드에서 string1과 string2의 주소값은 같다.
- 생성자 활용 방식
String string1 = new String("constructor");
String string2 = new String("constructor");
반면 생성자 활용 방식으로 String을 만들 경우 Heap 영역에 존재하게 된다.
이럴 경우 같은 데이터를 갖고 있어도 별개의 heap 메모리 주소를 할당한다.
즉, 위 코드에서 string1과 string2의 주소값은 다르다.
== vs .equals()
== 객체가 같은지 비교하지만 각각의 객체가 갖고있는 문자열을 비교하지는 않는다.
== 연산자의 경우 참조타입 변수들 간 동일한 객체를 참조하는 것인지를 알아볼 때 사용된다. 여기서 참조 타입 변수의 값은 Heap 영역의 주소이므로 즉, 주소 값을 비교하는 것이다.
반면 equals()는 두 비교대상의 데이터값을 비교한다. 따라서 자바에서 String 객체를 비교할 때는 .equals() 메서드를 사용하라고 한 것이었다.
ref)
https://coding-factory.tistory.com/536
https://sudo-minz.tistory.com/93
'[Java] > 문법, 자료구조, 알고리즘' 카테고리의 다른 글
Tree, BinaryTree (0) | 2023.04.02 |
---|---|
PriorityQueue (0) | 2023.04.01 |
StringTokenizer (0) | 2023.03.25 |
좌표 정렬 (0) | 2023.03.24 |
Heap (0) | 2023.03.21 |