Double 객체를 이용해 연산할 때 예외값인 NaN(Not A Number)를 진단하기 위해 Double 객체의 Double.NaN으로 비교하는 경우가 있는데, 안타깝게도 이 경우 개발자의 예측과는 다르게 동작하는 문제가 있다. 예제 1.21.1에서 볼 수 있듯이 errorValue가 Double.NaN 값으로 설정돼 있어도 Doubel.NaN과 같다고 인지하지 못하는 문제가 발생한다.
예제 1.21.1 잘못된 Double.NaN의 사용법
package com.software.basic.problem;
public class BadComparisonExample {
public static void main(String[] args) {
// 어떠한 이유로 숫자가 아닌 값(NaN; Not a Number)을 할당
Double errorValue = Double.NaN;
// 오류를 검증하기 위해 오류 값을 Double.NaN과 비교
if(errorValue == Double.NaN) {
System.out.println("오류 발생");
} else {
System.out.println("정상 처리");
}
}
}
실행 결과
정상 처리
문제점 진단
PMD에서는 이처럼 잘못된 값 비교를 방지하기 위해 BadComparison 룰을 제공해 Double.NaN으로 값을 비교하는 것을 경고하고 수정하도록 권고한다. 그림 1.21.1은 PMD를 이용해 Double.NaN으로 값을 비교한 코드를 진단한 결과다.
그림 1.21.1 Double.NaN으로 값을 비교한 코드를 BadComparison 룰로 진단한 결과
해결 방안
자바 언어 사양(JLS; Java Language Specification)에 따르면 NaN(Not a Number), 즉 숫자 아님은 정말 숫자가 아니여서 연산자를 이용한 NaN 간의 비교도 불가능하다고 설명한다. 따라서 예제 1.21.1과 같이 두 값이 모두 Double.NaN일 경우 errorValue == Double.NaN으로 비교하는 것은 무의미하다. 이러한 오류를 처리하려면 예제 1.21.2와 같이 isNaN 메서드를 이용해 비교해야 한다.
예제 1.21.2 올바른 Double.NaN 값의 비교 방법
package com.software.basic.solution;
public class BadComparisonExample {
public static void main(String[] args) {
// 어떠한 이유로 숫자가 아닌 값(NaN; Not a Number)을 할당
Double errorValue = Double.NaN;
// 오류를 검증하기 위해 오류 값을 Double.NaN으로 비교
if(Double.isNaN(errorValue)) {
System.out.println("오류 발생");
} else {
System.out.println("정상 처리");
}
}
}