[Java] ==, equals(), Objects.equals()

2025. 6. 30. 16:39·Study/Java

📝 개요

프로젝트를 진행하다보면 값을 비교해야되는 경우가 많이 있다. 예를 들어 사용자의 권한 상태가 “일반” 인지, “관리자” 인지 혹은 삭제 상태가 Y 인지, N인지 값의 일치를 비교한다.

 

Java 에서 객체(값) 비교는 상황에 따라 3가지 방식이 대표적으로 쓰인다. 비교 대상의 객체에 따라서 값 비교하는 방식이 다르고(배열, 컬렉션) 비교하는 기준에 따라서(정렬, 크기 등 : Comparator 인터페이스 활용) 개발자가 커스텀하여 비교하기도 한다.

 

다음은 값의 비교(일치/불일치) 가장 기본적으로 사용되는 방식에 대해서 알아보겠다.


🚀 “==” 비교 연산자 (Equality Operator)

1️⃣ 개념

== 는 Java 에서 비교연산자 이다. 기본 의미는 좌변과 우변이 같은가 를 비교하는 연산자이다. 비교 연산자는 비교 대상에 따라서 의미가 달라지는데

 

기본 타입(Primitive Type) : int, double, boolean, char, long, shor, float, byte 등 에서는 “값 자체” 가 같은지 비교 한다.

 

참조 타입(Reference Type) : String, 배열, 객체 등에서는 “객체가 동일한 인스턴스(메모리 상에서 완전히 같은 객체)” 인가를 비교(즉, ‘주소값’ 비교) 한다.

 

참조 타입에서 메모리 상에서 완전히 같은 객체라는 것은 메모리상에서 딱 하나, 같은 주소를 가리키고 있다는 것을 의미한다. 따라서 String 등 new 연산자로 생성한 객체는 ‘내용:값’ 이 같아도 == 로 비교하면 false 가 나올 수 있다.


2️⃣ 동작방식/원리

  • 기본 타입(Primitive Type) 에서 ==
    • int a = 1; int b = 1; a == b → true
    • 내부적으로 값 자체(비트)가 같은 지 비교
  • 참조 타입(Reference Type) 에서 ==
    • 겍체의 메모리 주소(참조값, Reference Value)를 비교
    • “Heap 에 올라간 객체가 같은가” / 즉, 동일한 객체(인스턴스)인가?
String a = new String("hi");
String b = new String("hi");
a == b // false (다른 주소, 각각 new로 생성)

String c = a;
a == c // true (같은 객체)

 

  • String 리터럴의 예외 상황
    • Java 는 String 리터럴 풀(Pool)을 이용해서 같은 리터럴은 공유한다.
String s1 = "hello";
String s2 = "hello";
s1 == s2 // true (둘 다 String Pool에서 같은 객체 가리킴)

String s3 = new String("hello");
s1 == s3 // false (new는 항상 새 인스턴스)

String Constant Pool 및 리터럴 방식에 대해서는 다른 포스팅에서 다룰 예정이다.

 

  • 배열, List, 객체 등 모든 참조 타입 동일
    • 배열, 객체 등 모든 참조 타입은 주소값만 비교한다.
int[] arr1 = {1,2,3};
int[] arr2 = {1,2,3};
arr1 == arr2 // false (내용 같아도 주소 다름)
arr1 == arr1 // true

 

  • null 비교
    • 어떤 객체가 null 인지 확인할 때 == 을 쓴다.
String s = null;
if (s == null) { ... }
// null == null 은 true (둘 다 같은 null 값)

 

  • Singleton Pattern, ENUM, 캐시 객체 비교
    • enum, 싱글턴 객체 등 “유일한 인스턴스”를 비교할 때만 == 을 의도적으로 사용한다.
if (status == Status.DONE) { ... }

 

[ Java 에서의 메모리 구조 기본 ]
Stack

  • 메서드 실행 시 지역 변수, 메서드 파라미터, 기본형(int, boolean 등) 이 저장 되는 공간
  • 함수 호출마다 Push/Pop 됨
  • 속도 빠름, 크기 작음

Heap

  • new 연산자로 생성한 “객체” 들이 저장되는 공간
  • 크기가 큼, 동적으로 객체(클래스 인스턴스) 저장)
  • GC(Garbage Collector)가 주기적으로 사용 안 하는 객체 정리
  • 객체의 실제 데이터(필드, 참조 등)와 주소(참조값)가 저장됨

Heap에 올라간 객체는 프로그램이 끝날 때까지, 또는 GC가 제거할 때까지 메모리에 남아있는다. Stack 변수는 함수/스코프가 끝나면 바로 사라진다. Heap 메모리에 올라간 실제 데이터를 Stack 에 참조값으로 저장한다. 이는 함수나 스코프가 끝나면 Stack 의 참조값은 사라지지만, 실제 데이터는 Heap에서 유지된다는 것을 의미한다.


🚀 equals()

1️⃣ 개념

equals() 메서드는 객체의 “동등성(내용)” 을 비교하는 메서드이다. 기본은 Object 클래스에서 상속받는다. 동등성이란 두 객체가 “논리적으로 같은 값/의미를 가지는가” 를 말한다.

  • 동일성 : ==, 같은 인스턴스인가(메모리 주소 비교)
  • 동등성 : equals(), 내용이 같은가(값 비교)

equals()는 객체의 “값” 이 같으면 같은 것으로 취급해야할 때 사용한다. 실무에서는 VO, DTO, 비즈니스 객체, 컬렉션의 중복 체크 등에 사용된다.


2️⃣ 동작방식/원리

[ Object 객체 정의 equals 함수 ]

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

Object 클래스에서의 equals()는 사실 == 과 똑같이 주소 비교만 한다. 즉, 오버라이딩 하지 않으면 == 와 결과는 완전히 동일하다. equals()는 반드시 hashCode() 와 함께 오버라이딩 되어야한다. HashMap/HashSet/Hash 기반 컬렉션에서 동등성을 유지해야하기 때문이다.

 

String, Integer, List, Date 등 거의 모든 표준 타입은 equals() 메서드에 대한 오버라이딩이 값만 비교하도록 되어있다. 그래서 표준 타입 객체 이외에 직접 만든 객체 같은 경우, equals() 와 hashCode() 대한 오버라이드가 되어 있지 않으면 == 연산자를 사용하는 것과 같다.

 

[ String 객체에서의 equals 함수 ]

// String.equals()
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    return (anObject instanceof String aString)
            && (!COMPACT_STRINGS || this.coder == aString.coder)
            && StringLatin1.equals(value, aString.value);
}

// StringLatin1.equals()
@IntrinsicCandidate
public static boolean equals(byte[] value, byte[] other) {
    if (value.length == other.length) {
        for (int i = 0; i < value.length; i++) {
            if (value[i] != other[i]) {
                return false;
            }
        }
        return true;
    }
    return false;
}

 

[ equals() 메서드 오버라이딩 후 사용 예시 ]

public class User {
    private String name;
    public User(String name) { this.name = name; }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return Objects.equals(name, user.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}
User u1 = new User("name");
User u2 = new User("name");
System.out.println(u1.equals(u2)); // true

Set<User> users = new HashSet<>();
users.add(u1);
System.out.println(users.contains(u2)); // true (equals/hashCode 오버라이딩된 경우)

// equals(), == 연산자 결과
User u1 = new User("name");
User u2 = new User("name");
System.out.println(u1 == u2); // false (주소 비교)
System.out.println(u1.equals(u2)); // true (내용 비교)

🚀 Objects.equals()

1️⃣ 개념

Objects.equals() 는 기존 equals() 메서드에서 두 비교 대상 값이 nullable 한 값이 들어오더라도 Null-safety 하게 비교 가능한 메서드이다. 두 객체를 비교할 때, 둘 중 하나라도 null 이면 NPE 없이 안전하게 비교하도록 만들어진 유틸리티 메서드이다.


2️⃣ 동작원리/방식

// Object a = nullable, Object b = nullable
public static boolean equals(Object a, Object b) {
     return (a == b) || (a != null && a.equals(b));
}

둘 중 하나라도 null 이 될 수 있는 상황에서 equals 비교가 필요할 때 사용된다. 예를 들어 데이터베이스에서 값이 비어있을 수도 있을 때, 파라미터로 들어온 객체가 null 일 수도 있을 때, if문에서 바로 비교하고 싶을 때 사용한다.


'Study > Java' 카테고리의 다른 글

[Java] Utility Class  (0) 2025.06.03
[Java] record  (0) 2025.06.03
'Study/Java' 카테고리의 다른 글
  • [Java] Utility Class
  • [Java] record
arraysort
arraysort
arraysort 님의 블로그 입니다.
  • arraysort
    arraysort 님의 블로그
    arraysort
  • 전체
    오늘
    어제
    • 분류 전체보기 (14)
      • Study (5)
        • Java (3)
        • DataBase (1)
        • Spring-Boot (1)
        • React (0)
        • WEB (0)
      • Project (9)
        • Backend (5)
        • Frontend (2)
        • Database (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    spring boot
    Database
    TypeScript
    FilterChain
    mabatis
    utilityclass
    API
    objects.eqauls()
    react
    VO
    java
    SQL Mapper
    lombok
    Groupware
    SQL
    oracle
    backend
    Spring Security
    CDB
    DTO
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
arraysort
[Java] ==, equals(), Objects.equals()
상단으로

티스토리툴바