2009-07-29 5 views
164

Strings을 비교할 때 ==에 몇 가지 문제점이 있다는 것을 알고 있습니다. String.equals()은 더 나은 접근 방법입니다. 자, 저는 JUnit 테스트를하고 있습니다. 제 성향은 assertEquals(str1, str2)입니다. 이것은 동일한 내용을 담고있는 두 문자열을 주장하는 신뢰할 수있는 방법인가? assertTrue(str1.equals(str2))을 사용 하겠지만, 예상 값과 실제 값이 실패한 것을 확인하는 이점을 얻지 못합니다.Java : assertEquals (String, String)가 안정적입니까?

관련 메모에 누구나 str1 == str2의 문제를 명백하게 설명하는 페이지 또는 스레드에 대한 링크가 있습니까?

+1

확실하지 않은 경우 코드 또는 Javadoc을 읽을 수 있습니다. BTW 만약 당신이 assertSame 사용할 수있는 동일한 개체를 테스트하고 싶습니다. –

+2

str1 및 str2가 null 인 경우 assertEquals()가 true이지만 assertTrue (str1.equals (str2))가 예외를 throw합니다. 첫 번째 예제는 str1과 str2의 내용과 같은 유용한 오류 메시지도 출력합니다. 두 번째 예제는 유용하지 않습니다. –

답변

226

당신이해야 항상 사용 .equals() 자바 Strings을 비교.

JUnit은 .equals() 메서드를 호출하여 assertEquals(Object o1, Object o2) 메서드에서 동등성을 결정합니다.

따라서 assertEquals(string1, string2)을 사용하는 것이 안전합니다. ==.equals()과의 차이점에 대하여 (String들 때문에 Object S)

Here is a link to a great Stackoverflow question.

+11

두 문자열이 모두 null 인 경우 IIRC assertEquals()가 성공합니다. 이것이 원하는 것이 아니라면 assertNotNull()을 호출하십시오. – finnw

+0

@ finnw, 소스를 확인하면 실제로 맞습니다. –

+10

추가적으로, ==를 테스트하고 싶다면 assertSame()을 호출 할 수 있습니다. – james

3

예, 테스트를 위해 항상 사용됩니다. 테스트 프레임 워크는 이와 같은 비교에 .equals()를 사용합니다.

다음은 "문자열 평등 오류"를 설명하는 링크입니다. 본질적으로 Java의 문자열은 객체이며 객체 평등을 비교하면 일반적으로 내용이 아니라 메모리 주소를 기준으로 비교됩니다. 이 때문에 두 문자열은 내용이 동일해도 동일한 주소를 차지하지 않으므로 인쇄 할 때 동일하게 보이더라도 정확하게 일치하지 않습니다.

http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/

3
public class StringEqualityTest extends TestCase { 
    public void testEquality() throws Exception { 
     String a = "abcde"; 
     String b = new String(a); 
     assertTrue(a.equals(b)); 
     assertFalse(a == b); 
     assertEquals(a, b); 
    } 
} 
2

JUnit을 assertEquals(obj1, obj2)은 참으로 obj1.equals(obj2) 전화 않습니다.

obj1 == obj2 않습니다 assertSame(obj1, obj2)있다 당신이 피하려고하는지 인 (즉, obj1obj2같은 인스턴스를 참조하고 있는지 확인합니다).

그럼 괜찮습니다.

4

간단히 말해서 동일한 문자를 포함하지만 다른 객체 (다른 메모리 위치에있는) 인 두 개의 String 객체를 가질 수 있습니다. == 연산자는 두 개의 참조가 같은 객체 (메모리 위치)를 가리키고 있는지 확인하지만 equals() 메서드는 문자가 같은지 검사합니다.

보통 두 문자열에 동일한 문자가 포함되어 있는지 확인하는 데 관심이 있습니다 (동일한 메모리 위치를 가리키는 지 여부는 확인하지 않습니다).

+0

Thumbs up, 정확히 문자열의 값 또는 메모리 위치의 값입니다. – Pomagranite

26

assertEquals은 비교를 위해 equals 방법을 사용합니다. == 연산자를 사용하는 다른 어설 션 인 assertSame이 있습니다.

==이 문자열과 함께 사용되어서는 안되는 이유를 이해하려면 ==을 이해해야합니다. 신원 확인을 수행합니다. 즉, a == bab같은 개체을 참조하는지 확인합니다. 그것은 언어에 내장되어 있으며, 다른 클래스에 의해 그 동작을 변경할 수 없습니다. 반면에 equals 메서드는 클래스에 의해 재정의 될 수 있습니다. 기본 동작 (Object 클래스)은 == 연산자를 사용하여 신원 확인을 수행하는 반면 String을 비롯한 많은 클래스는이를 대체하여 "동등성"검사를 대신합니다. String의 경우 과 b이 동일한 개체를 참조하는지 확인하는 대신 a.equals(b)은 참조하는 개체가 모두 정확히 동일한 문자를 포함하는 문자열인지 확인합니다.

유추 시간 : 각 String 개체는 그 위에 무엇인가가 쓰여진 종이라는 것을 상상해보십시오. 두 개의 종이에 "Foo"라고 적혀 있고, 다른 하나는 "Bar"로 쓰여져 있다고 가정 해 봅시다. 첫 번째 두 장을 받아 ==을 사용하여 비교하면 false이 반환됩니다. 왜냐하면 본질적으로 "이것들은 같은 종이입니까?"라고 묻기 때문입니다. 그것은 종이에 쓰여진 것을 보지 않아도됩니다. 두 개의 종이가 아닌 두 장의 종이를주고 있다는 사실은 false을 반환한다는 것을 의미합니다. 그러나 equals을 사용하는 경우 equals 메서드는 두 개의 종이를 읽고 동일한 내용 ("Foo")을 사용하므로 true을 반환합니다.

Strings와 혼동스럽게되는 비트는 Java가 "interning"Strings 개념을 갖고 있으며 이는 코드의 문자열 리터럴에서 자동으로 수행된다는 것입니다. 즉, 코드에 두 개의 동일한 문자열 리터럴이있는 경우 (서로 다른 클래스에 있어도) 실제로는 모두 동일한 String 객체를 참조하게됩니다. 이렇게하면 == 연산자가 true 번보다 더 자주 반환 될 수 있습니다.

+0

"즉, a == b는 a와 b가 같은 객체인지 확인합니다."기술적으로 a와 b가 참조이기 때문에 a와 b가 같은 객체를 참조하는지 확인합니다. 내가 틀린 것이 아니라면 – andy

+0

@ user1903064 맞습니다. 비 기본 변수는 Java에서 참조를 포함 할 수 있기 때문에 추가로 건너 뛰는 것이 일반적입니다 그들에 대해 이야기 할 때 간접적 인 수준이지만, 나는이 경우 좀더 명확한 것이 유익하다는 것에 동의한다.답변을 업데이트했습니다. 제안 해 주셔서 감사합니다! –

관련 문제