Objects.equals 메소드의 구덩이

서문: Objects.equals() 메서드는 java.util의 도구 클래스로, 번거로운 널 포인터 판단을 피하면서 두 객체의 같음을 비교하는 데 사용할 수 있습니다.

이 문서는 소스 코드 중단점 디버깅으로 분석된 코드 예제와 Objects.equals() 메서드를 사용할 때 쉽게 간과되는 몇 가지 문제로 확장됩니다.

1. Objects.equals() 공식 소스 코드

这里我们先看Objects.equals()的官方源码

    /**
     * Returns {@code true} if the arguments are equal to each other
     * and {@code false} otherwise.
     * Consequently, if both arguments are {@code null}, {@code true}
     * is returned and if exactly one argument is {@code null}, {@code
     * false} is returned.  Otherwise, equality is determined by using
     * the {@link Object#equals equals} method of the first
     * argument.
     *
     * @param a an object
     * @param b an object to be compared with {@code a} for equality
     * @return {@code true} if the arguments are equal to each other
     * and {@code false} otherwise
     * @see Object#equals(Object)
     */
    public static boolean equals(Object a, Object b) {
    
    
        return (a == b) || (a != null && a.equals(b));
    }

2. 다음 코드의 실행 결과 분석

    public static void main(String[] args) {
    
    
        Integer integer1 = Integer.valueOf(1);
        Integer integer200 = Integer.valueOf(200);
        Integer integer100 = Integer.valueOf(100);
        Long long200 = 200L;
        Byte Byte100 = (byte) 100;
        byte byte100 = (byte) 100;
        System.out.println("--------------------Integer-----------------------");
        System.out.println(Objects.equals(integer1, 1));         // true
        System.out.println(Objects.equals(integer200, 200));     // true
        System.out.println(Objects.equals(integer100, byte100));    // false
        System.out.println(Objects.equals(integer100, Byte100));    // false
        System.out.println("--------------------Long--------------------------");
        System.out.println(Objects.equals(long200, 200L));      // true
        System.out.println(Objects.equals(long200, 200));       // false
        System.out.println(Objects.equals(long200, integer200));    //false
        System.out.println("--------------------Byte--------------------------");
        System.out.println(Objects.equals(Byte100, 100));       // false
        System.out.println(Objects.equals(Byte100, (byte) 100));    // true
        System.out.println(Objects.equals(Byte100, byte100));       // true
        System.out.println("--------------------byte--------------------------");
        System.out.println(Objects.equals(byte100, 100));       // false
        System.out.println(Objects.equals(byte100, (byte) 100));   // true
        System.out.println(Objects.equals(100,byte100));        // false
    }

3. 주요 질문에 대한 답변

3.1 System.out.println(Objects.equals(정수100, 바이트100));

둘 다 인데 赋值100비교를 위해 Objects.equals()를 사용했을 때 return이 false로 나오는데 왜 그럴까요? 다음으로 그림과 같이 소스 코드에서 디버깅을 중단합니다.
1단계, 중단점 설정
여기에 이미지 설명 삽입
2단계, 중단점에서 Objects.equals() 메서드로 이동합니다.
byte100 기본 데이터 유형 변수가 삭제된 것을 볼 수 있습니다. 自动装箱为Byte包装类, 다음 단계는 Integer의 equals 메서드입니다
여기에 이미지 설명 삽입
세 번째 단계는 메서드에 침입하는 것입니다 Integer.equals()Byte가 Integer의 인스턴스가 아니기 때문에 Integer.equals() 메서드는 값을 비교하는 대신 직접 false를 반환하는 것을 볼 수 있습니다 .
여기에 이미지 설명 삽입

3.2 System.out.println(Objects.equals(long200, 200));

하나는 200L이고 다른 하나는 200입니다. 이는 우리의 관성적 사고에 대해 확실히 참으로 간주되지만 비교를 위해 Objects.equals()를 사용할 때 우리는 다음을 발견합니다. 왜 그럴까요 返回的是false? 다음으로 그림과 같이 소스 코드에서 디버깅을 중단합니다.
1단계, 중단점 설정 2단계, 여기에서 200의 기본 데이터 유형(int)이 3 단계
여기에 이미지 설명 삽입
에서 설정되었음을 알 수 있습니다. 단계에서 중단점은 직접 이동 Long.equals() 메서드에서 그림과 같이: 둘은 전혀 동일한 개체 유형이 아니므로 직접 false를 반환하므로 원칙은 위의 3.1과 동일합니다.自动装箱为Integer
여기에 이미지 설명 삽입


여기에 이미지 설명 삽입

요약: 위 문제의 본질적인 이유는 Object.equals() 메서드를 사용할 때 기본 데이터 유형이 자동으로 박싱된 다음 해당 래퍼 클래스의 같음 비교가 수행되기 때문입니다. 그리고 우리는 그것을 무시하고 类型的比较값의 비교에만 주의를 기울였습니다.

사실 이것은 Objects.equals() 메서드의 구덩이가 아닙니다. 단지 우리가 그것을 당연하게 여기고 그것이 컴퓨터 코드의 실행과 일치하지 않는다는 것을 이해한다는 것입니다. 이것은 또한 우리에게 다음을 알려줍니다. 원인. 다른 사람이 만든 바퀴를 사용할 때 코드를 빠르고 효율적으로 작성할 때 해당 기능 경계, 사용 시나리오 및 실패 시나리오를 명확히 해야 버그가 적은 올바른 코드를 작성할 수 있습니다.

추천

출처blog.csdn.net/lzq2357639195/article/details/131166898