JAVA/BASIC

자바(JAVA) == 비교연산자와 Object클래스의 equals() 메소드

유혁스쿨 2023. 4. 12. 12:30
728x90
반응형

비교연산자

 

비교연산자는 일반 데이터 혹은 변수에 저장된 데이터의 값이 같은지, 다른지 조사한다.

참조 타입 변수들 간의 비교 연산은 동일한 객체를 참조하는지, 다른 객체를 참조하는지 알아볼 때 사용한다.

참조 타입 변수의 값은 힙 영역의 객체 주소이므로 결국 주소값을 비교하는 것이 된다.

동일한 주소 값을 갖고 있다는 것은 동일한 객체를 참조한다는 의미이다.

따라서 동일한 객체를 참조하고 있을 경우 동등비교(==)연산의 결과는 true이고 부정비교(!=) 연산 결과는 false가 된다

public class Example {
    public static void main(String... args) {
        Car car1 = new Car("블루",12); // 힙영역에 car1 저장
        Car car2 = new Car("블루",12); // 힙영역에 car2 저장
        System.out.println(car1==car2); // [false] 각각의 객체 주소 비교
        System.out.println(car1!=car2); // [true] 각각의 객체 주소 비교
    }
}

class Car {
    String color;
    Integer number;

    public Car(String color, Integer number) {
        this.color = color;
        this.number = number;
    }
}

위 코드에서 car1과 car2는 동일한 값을 갖는 Car클래스의 객체이지만 각각 다른 영역에 저장된다.

이것이 자바다 그림 예

위 그림에서 refVar1과 refVar2는 서로 다른 객체를 참조 하고 있으므로 동등 비교시 false, 부정 비교는 true를 리턴한다.

반면, refVar2와 refVar3는 서로 같은 객체를 참조 하고 있으므로 동등 비교시 true, 부정 비교시 false를 리턴한다.

public class Example {
    public static void main(String... args) {
        Car car1 = new Car("블루",12);
        Car car2 = new Car("블루",12);
        car2 = car1; // car2에 car1 객체 저장
        System.out.println(car1==car2); // [true] 각각의 객체 주소 비교
        System.out.println(car1!=car2); // [false] 각각의 객체 주소 비교
    }
}

class Car {
    String color;
    Integer number;

    public Car(String color, Integer number) {
        this.color = color;
        this.number = number;
    }
}

 

 

Object 의 equals()

public boolean equals(Object obj) {
        return (this == obj);
}

equals 메소드의 매개 타입은 Object이다. 이것은 모든 객체가 매개값으로 대입될 수 있음을 말한다.

그 이유는 Object가 자바 모든 객체의 최상위 타입이므로 모든 객체는 Object 타입으로 자동 타입 변환될 수 있기 때문이다.

위 코드에서 볼 수 있듯 Object 클래스의 equals() 메소드는 비교 연산자인 ==과 동일한 결과를 리턴한다.

동등 비교를 한다는 뜻은 다시말해 객체의 주소를 비교하는것이다.

두 객체 변수가 힙영역에 저장된 하나의 동일한 객체라면 true를 리턴하고 그렇지 않으면 false를 리턴한다.

public class Example {
    public static void main(String... args) {
        Car car1 = new Car("블루",12);
        Car car2 = new Car("블루",12);
        System.out.println(car1.equals(car2)); // [false] 각각의 객체 주소 비교
    }
}

class Car {
    String color;
    Integer number;

    public Car(String color, Integer number) {
        this.color = color;
        this.number = number;
    }
}

 

String, Integer의 equals()

자바에서는 두 객체를 동등 비교할 떄 equals() 메소드를 흔히 사용한다.

equals() 메소드는 두 객체를 비교해서 논리적으로 동등하면 true를 리턴하고, 그렇지 않으면 false를 리턴한다.

논리적으로 동등하다는 것은 같은 객체이건 다른 객체이건 상관없이 객체가 저장하고 있는 데이터가 동일함을 뜻한다.

예를들어 String 객체의 equals() 메소드는 String 객체의 번지를 비교하는 것이 아니고, 문자열이 동일한지 조사해서 같다면 true를 리턴하고, 그렇지 않다면 false를 리턴한다.

이것이 가능한 이유는 String클래스가 Object 클래스의 equals() 메소드를 재정의(Overriding) 해서 번지 비교가 아닌 문자열 비교로 변경했기 때문이다.

 

[String 클래스의 equals() 메소드]

public boolean equals(Object anObject) {
    if (this == anObject) { // 매개변수의 문자열과 메소드호출 대상의 인스턴스의 번지가 같다면 true
        return true;
    }
    if (anObject instanceof String) { // 매개변수가 String 타입인지 체크
        String aString = (String)anObject; // String 타입으로 다운캐스팅
        if (coder() == aString.coder()) { // 
        // Latin1과 UTF16 인지 도출하여 equals메소드를 통해 문자열 하나씩 비교
            return isLatin1() ? StringLatin1.equals(value, aString.value)
                              : StringUTF16.equals(value, aString.value);
        }
    }
    return false;
}

[Integer 클래스의 equals() 메소드]

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        //Integer객체로 강제 타입변환 훟 기본타입의값을 논리적으로 비교한다.
        return value == ((Integer)obj).intValue(); 
    }
    return false;
}

이와같이 Object의 equals() 메소드는 직접 사용되지 않고 하위 클래스에서 재정의하여 논리적으로 동등 비교 할 때 사용한다.

 

Car 객체는 다르지만 color 필드 값이 같으면 논리적으로 동등한 객체로 취급하고 싶을 경우 Object의 equals() 메소드를 재정의해서 color 필드값이 같음을 비교하면 된다.

public class Example {
    public static void main(String... args) {
        Car car1 = new Car("블루",12);
        Car car2 = new Car("블루",12);
        System.out.println(car1.equals(car2)); // 오버라이딩 된 equals를 통해 번지비교가 아닌 논리적 동등 비교
    }
}

class Car {
    String color;
    Integer number;

    public Car(String color, Integer number) {
        this.color = color;
        this.number = number;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Car) {
            Car car = (Car) obj;
            if (this.color.equals(car.color) && this.number.equals(car.number)) {
                return true;
            }
        }
        return false;
    }
}
728x90
반응형