Java의 데이터 유형은 두 가지 유형으로 나눌 수 있습니다. int, double 및 boolean과 같은 기본 유형과 String 및 List와 같은 참조 유형입니다.
그리고 각 기본형에 해당하는 참조형이 있습니다. 래핑된 기본 유형그것은 말한다.
예를 들어 int, double 및 boolean에 해당하는 boxed primitives는 Integer, Double 및 Boolean입니다.
6번 항목에서 언급한 바와 같이 autoboxing과 autounboxing을 사용하면 큰 차이 없이 두 가지 유형을 사용할 수 있지만 그렇다고 해서 차이가 없어지지는 않습니다. 둘 사이에는 분명한 차이가 있으므로 어떤 유형을 사용하느냐가 매우 중요합니다. 즉, 신중하게 선택해야 합니다.
프리미티브 유형과 프레임 프리미티브 유형 사이에는 세 가지 주요 차이점이 있습니다.
- 첫째, 기본 유형에는 값만 있는 반면 중첩된 기본 유형에는 값이 있습니다. 신원즉, boxed primitive type의 두 인스턴스는 값이 같더라도 서로 다른 것으로 식별할 수 있습니다.
- 둘째, 기본 유형의 값은 항상 유효하며, boxed primitive type은 유효하지 않은 값, 즉 null을 가질 수 있습니다.
- 셋째, 기본 형식은 중첩된 기본 형식보다 낫습니다. 시간 및 메모리 사용 측면에서 더 효율적오전.
이 세 가지 차이점을 부주의하게 사용하면 실제 문제가 발생할 수 있습니다.
다음은 정수 값을 오름차순으로 정렬하는 비교기입니다. 비교기의 비교 방법은 첫 번째 요소가 두 번째 요소보다 작으면 음수를 반환하고 같으면 0을, 더 크면 양수를 반환합니다. ) . 정수는 자체적으로 정렬되므로 이 비교기는 실제 의미가 없지만 매우 흥미로운 점을 보여줍니다.
Comparator<Integer> naturalOrder =
(i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);
특정 문제를 정확히 지적하기 어렵고 실제로 이것 저것 테스트 한 후에도 잘 지속됩니다. 예를 들어 백만 개의 항목 목록과 이 비교를 사용하여 Collections.sort를 실행하면 문제가 없습니다. 목록에 중복이 있는지 여부는 중요하지 않습니다. 그러나 심각한 오류가 숨어 있습니다 …
이 오류를 시각적으로 확인하려면 naturalOrder.compare(new Integer(42), new Integer(42)) 값을 출력하십시오.
두 정수 인스턴스의 값이 42로 같기 때문에 0이 출력되어야 하지만 실제로는 1이 출력됩니다. 즉, 첫 번째 정수가 두 번째 정수보다 크다고 주장합니다.
원인은 무엇입니까? naturalOrder(i < j)의 첫 번째 검사는 잘 작동합니다. 여기서 i와 j가 참조하는 오토박스 정수 인스턴스는 기본 값으로 변환됩니다. 그런 다음 첫 번째 정수 값이 두 번째 정수 값보다 작은지 여부를 평가합니다. 적지 않으면 두 번째 테스트(i == j)가 수행됩니다. 그러나 이번 2차 시험에서는 두 ‘개체 참조’의 구별 가능성검사할 것이다
i와 j가 서로 다른 정수 인스턴스인 경우(동일한 값이 있더라도) 이 비교 결과는 다음과 같습니다. 잘못된, 비교기는 1(거짓)을 반환합니다. 즉, 첫 번째 정수가 두 번째 정수보다 큽니다. 이와 같이 (동일한 객체를 비교하지 않는 한) 중첩된 기본 유형에서 == 연산자를 사용하는 것은 오류입니다.
실제로 이와 같은 기본 유형을 처리하는 비교기가 필요한 경우 Comparator.naturalOrder()를 사용합니다.
자체 비교를 생성하는 경우 기본 유형을 허용하는 비교 생성 방법 또는 정적 비교 방법을 사용해야 합니다(항목 14). 이 문제를 해결하려면 각각 중첩된 정수 매개변수의 값을 기본 유형 정수로 저장한 다음 해당 기본 유형 정수에 대한 모든 비교를 수행하는 두 개의 로컬 변수가 있어야 합니다. 이렇게 하면 오류의 원인이 되는 신원 확인을 피할 수 있습니다.
Comparator<Integer> naturalOrder = (iBoxed, jBoxed) -> {
int i = iBoxed, j = jBoxed;
return i < j ? -1 : (i == j ? 0 : 1);
};