문자열 비교할때 ==말고 equals()를 사용해야한다.

이규훈·2023년 5월 26일
post-thumbnail

문자열 비교를 할 때에는 == 연산자 대신 equals() 메소드를 사용해야 합니다. ==는 객체의 레퍼런스를 비교하고, equals()는 객체의 값을 비교합니다. String 객체에서 ==를 사용하면 예상치 못한 결과를 얻을 수 있습니다. 따라서 값 비교를 원할 때는 항상 equals()를 사용하는 것이 좋습니다.

이에 대한 설명을 위해서는 자바에서 ==연산자와 equals()메소드가 어떻게 동작하는지, 그리고 String이 어떻게 동작하는지 이해해야 합니다.

== 연산자 vs equals() 메소드

  • == 연산자: 두 참조 변수가 같은 객체를 가리키고 있는지 확인합니다. 즉, 두 참조 변수의 메모리 주소를 비교합니다. 이는 기본 데이터 타입(예: int, char, boolean 등)과 참조 타입(객체) 모두에 사용할 수 있습니다.
  • equals() 메소드: 두 객체의 실제 내용이 같은지를 확인합니다. 이 메소드는 Object 클래스에서 상속받는 메소드이며, 클래스에 따라 오버라이드해서 사용하는 경우가 많습니다.

String에 적용되는 == 연산자와 equals() 메소드

자바의 String 클래스는 불변(immutable)이기 때문에, 한 번 생성된 String 객체는 변경할 수 없습니다. 새로운 값을 할당하면 새로운 String 객체가 생성되고, 기존 객체는 변경되지 않습니다.

이 때문에, String 객체를 직접 생성(new String("abc"))하면 메모리에 새로운 객체가 할당되고, 리터럴을 사용해 생성(String s = "abc")하면 동일한 값에 대해 중복 생성을 피하기 위해 String 풀(String Pool)에 저장된 객체를 재사용합니다.

String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");

System.out.println(str1 == str2);       // true, 같은 String 풀 내의 "abc"를 참조
System.out.println(str1 == str3);       // false, str3는 새로 생성된 다른 객체를 참조
System.out.println(str1.equals(str2));  // true, 내용이 같음
System.out.println(str1.equals(str3));  // true, 내용이 같음

위 코드에서 == 연산자는 str1과 str2가 동일한 객체를 참조하므로 true를 반환하지만, str1과 str3는 서로 다른 객체를 참조하므로 false를 반환합니다. 반면 equals() 메소드는 객체의 내용을 비교하므로 모든 경우에 true를 반환합니다.

따라서 자바에서 String의 값을 비교할 때는 equals() 메소드를 사용하는 것이 좋습니다. == 연산자를 사용하면 예상치 못한 결과를 얻을 수 있습니다.

따라서 저도 현재 하고 있는 프로젝트에 ==대신 equals()를 사용하고 있습니다.

추가설명

불변 클래스(Immutable Class)

불변 클래스는 인스턴스가 한 번 생성되면 그 상태를 변경할 수 없는 클래스를 의미합니다. 즉, 객체의 필드 값이 생성 후 변경되지 않습니다. 이러한 불변 클래스는 여러 장점이 있습니다:

  • 스레드 안전성(Thread-safety): 불변 객체는 여러 스레드에서 동시에 사용되어도 그 상태가 바뀌지 않으므로, 동기화를 걱정할 필요가 없습니다. 이는 멀티스레드 환경에서 큰 장점이 됩니다.
  • 해시 테이블에 대한 키로 사용하기 좋음: 객체가 불변하면 그 해시코드도 불변합니다. 따라서 HashMap, HashSet 같은 해시 기반의 컬렉션에 키로 사용하기 적합합니다.
  • 참조 투명성(Referential transparency): 불변 객체는 상태가 변경되지 않으므로, 어느 시점에서 참조하더라도 동일한 값을 반환합니다. 이는 프로그램의 예측 가능성과 유지보수성을 높입니다.

String 클래스

Java에서 String 클래스는 대표적인 불변 클래스입니다. 즉, 한 번 생성된 String 객체의 상태는 절대로 변경되지 않습니다.

String str1 = "Hello, ";
str1 += "World!";  // 새로운 String 객체를 생성하고, str1은 새로운 객체를 참조하게 됩니다.

위의 코드에서 str1 += "World!";라는 연산이 수행될 때, 원래 str1이 참조하던 "Hello, "라는 String 객체의 내용이 바뀌는 것이 아니라, "Hello, World!"라는 새로운 String 객체가 생성되고, str1은 이 새로운 객체를 참조하게 됩니다. 원래의 "Hello, "라는 String 객체는 변경되지 않습니다.

String 클래스가 불변성을 유지하는 이유는 여러 가지가 있습니다:

  • 보안: String은 파일 이름, 네트워크 연결에 사용되는 URL 등 시스템에서 중요한 역할을 하는 데이터를 저장하는 데 사용됩니다. 불변성은 이러한 정보가 변조되는 것을 방지합니다.
  • 신뢰성: String 객체는 자주 공유되는데, 만약 한 곳에서 String 객체를 변경하면 다른 곳에서는 예기치 못한 동작을 하게 될 수 있습니다. 불변성을 통해 이를 방지합니다.
  • 성능 최적화: String은 문자열 리터럴을 통해 생성할 경우, JVM은 동일한 문자열이 이미 메모리에 있는지 확인하고 있으면 해당 String 객체를 재사용합니다. 이를 String 풀(String Pool)이라고 부릅니다. 이렇게 하면 메모리 사용량을 줄이고 성능을 최적화할 수 있습니다. 이 기능은 String이 불변성을 가지므로 가능합니다.
profile
개발취준생

1개의 댓글

comment-user-thumbnail
2023년 5월 26일

아주 정리를 잘하셨네요!!! ^^

답글 달기