2014-05-20 3 views
3

FindBugs 내 코드에서 다음과 같은 버그를 인식 참조합니다. 내가 아는 한 데이터 유형 필드 인 Long을 비교하려면 == 연산자를 사용해야합니다.자바 FindBugs는 : 긴 참조</p> </blockquote> <p>의</p> <blockquote> <p>의심스러운 비교 나는이 특정 오류를 인터넷 검색을 시도하지만 행운 : 롱의 의심스러운 비교

if (materialDefinition.getId() == definitionToRemoveFromClass.getId()) { 
    //... 
} 

나는 두 가지 방법이 Long을 반환 .getId() 확신합니다.

이 문제가 실제로 발생합니까? 그렇다면 해결 방법은 무엇입니까?

+2

이러한 long은 원시 유형입니까, 아니면 객체입니까? (java.lang.Long) 그들은 서로 다른 두 가지입니다 – DirkyJerky

+0

FindBugs의 어떤 버전에서이 규칙이 정의됩니까? 버전 3.0.1 (http://findbugs.sourceforge.net/bugDescriptions.html)에 대한 설명 목록에서 해당 코드를 찾을 수 없으며 향상된 코드 안전성을 위해 활성화하려고합니다. –

답변

11

정말 문제입니까, 그렇다면 어떻게 수정합니까?

예, 그 비교 false되는 발생합니다 참조하지 값 때문에 동일한 값을 갖는 두 개의 서로 다른 Long 인스턴스를 비교하고 있습니다. 대신 Long#equals()를 사용해야합니다 null을 반환 할 수 있습니다

final Long id1 = materialDefinition.getId(); 
final Long id2 = definitionToRemoveFromClass.getId(); 

if (id1.equals(id2)) { 
    //... 
} 

getId() 경우, 또한 적절한 null 검사를 포함해야합니다 (getId()null을 반환해야하는 방법 같은 소리하지 않지만).

0

당신은 더 나은

if (materialDefinition.getId().equals(definitionToRemoveFromClass.getId()))materialDefinition.getId()이 null이 있는지 확인 사용하십시오.

==의 B : A.compareTo(B) == 0

< B : A.compareTo(B) < 0

A> B : A.compareTo(B) > 0

1

.compareTo() 방법을 사용할 수 있습니다 (<>)이 값을 비교하려면 이런 식으로 할 수도 있습니다.

public static boolean equals(Long a, Long b){ 
    if (a==null && b==null) return true; 
    else if ((a==null) != (b==null)) return false; 
    else return a.equals(b); 
} 
+2

아니면 그냥'Objects.equals (a, b)'를 사용하십시오. – skiwi

0

예는 나쁜 냄새, 그리고 위의 @arshajii 설명대로, 대신 equals() 방법을 사용해야합니다.

내가 가장 흥미를 끈 것은 작은 값 (-128에서 127)으로 시작하는 것처럼 이러한 비교가 때때로 작동 할 수도 있다는 사실입니다. 더 큰 숫자의 경우에는 중단됩니다. 예를 들면 다음과 같습니다.

@Test 
public void compareSmallIds() { 
    Long id1 = 127L; 
    Long id2 = 127L; 

    Assert.assertTrue(id1 == id2); 
    Assert.assertTrue(id1.equals(id2)); 
    Assert.assertTrue((long) id1 == (long) id2); 
    Assert.assertTrue(id1.longValue() == id2.longValue()); 
} 

@Test 
public void compareIds() { 
    Long id1 = 500L; 
    Long id2 = 500L; 

    Assert.assertFalse(id1 == id2); 
    Assert.assertTrue(id1.equals(id2)); 
    Assert.assertTrue((long) id1 == (long) id2); 
    Assert.assertTrue(id1.longValue() == id2.longValue()); 
} 

이 동작은 숫자 값 범위가 기본값 인 숫자 캐시 정책 정의를 기반으로합니다. 그러나 확실히 원시가 아닌 값을 가진 코드는 값 비교를 위해 == 연산자에 의존해서는 안됩니다!