[Java] 6. 참조 타입의 == 연산과 equals() 메소드

김정란·2025년 5월 30일

Java

목록 보기
6/7

📋 목차

  1. 참조 타입과 기본 타입의 차이
  2. == 연산자의 동작 원리
  3. equals() 메소드와의 차이점
  4. String의 특별한 경우
  5. 배열과 참조 타입 비교
  6. 주의사항 및 팁
  7. 마무리

1. 참조 타입과 기본 타입의 차이

Java에서 변수가 저장하는 값은 기본 타입참조 타입에 따라 완전히 다름.

기본 타입 (Primitive Type)

  • 변수에 실제 값을 직접 저장
  • int, char, boolean, double
int a = 10;  // 변수 a에 실제 값 10을 저장
int b = 10;  // 변수 b에 실제 값 10을 저장

참조 타입 (Reference Type)

  • 변수에 객체의 메모리 주소를 저장
  • String, 배열, 클래스
String name = new String("Hong");  // name에는 "Hong" 객체의 주소가 저장됨
String name2 = new String("Hong"); // name2에는 다른 "Hong" 객체의 주소가 저장됨

2. == 연산자의 동작 원리

== 연산자는 변수에 저장된 값을 비교함. 여기서 핵심은 "값"이 무엇인지 이해하는 것임.

기본 타입에서의 == 연산

int x = 5;
int y = 5;
System.out.println(x == y); // true - 실제 값 5와 5를 비교

참조 타입에서의 == 연산

String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2); // false - 서로 다른 메모리 주소를 비교

// 같은 객체를 참조하는 경우
String str3 = str1;
System.out.println(str1 == str3); // true - 같은 메모리 주소를 비교

비유: 두 사람이 같은 내용의 편지를 가지고 있더라도, 각자의 집 주소는 다름. ==는 집 주소를 비교하는 것과 같음.


3. equals() 메소드와의 차이점

equals() 메소드는 객체의 내용을 비교하도록 설계됨.

String name = new String("Hong");
String name2 = new String("Hong");

System.out.println(name == name2);       // false - 주소 비교
System.out.println(name.equals(name2));  // true - 내용 비교

주요 차이점 정리

연산자/메소드기본 타입참조 타입
==실제 값 비교메모리 주소 비교
equals()사용 불가객체 내용 비교

4. String의 특별한 경우

String은 참조 타입이지만 리터럴 방식으로 생성할 때 특별한 동작을 함.

// 리터럴 방식 - String Pool에서 같은 객체 재사용
String name3 = "Hong";
String name4 = "Hong";
System.out.println(name3 == name4); // true - 같은 주소 참조

// new 키워드 방식 - 항상 새로운 객체 생성
String name5 = new String("Hong");
String name6 = new String("Hong");
System.out.println(name5 == name6); // false - 다른 주소 참조

String Pool: Java가 메모리 효율성을 위해 동일한 문자열 리터럴을 하나의 객체로 관리하는 특별한 메모리 영역


5. 배열과 참조 타입 비교

배열도 참조 타입이므로 == 연산 시 주소를 비교함.

int[] arr1 = {1, 2, 3};
int[] arr2 = {1, 2, 3};  // 내용은 같지만 다른 객체
int[] arr3 = arr1;       // 같은 객체를 참조

System.out.println(arr1 == arr2);        // false
System.out.println(arr1.equals(arr2));   // false (배열은 equals가 재정의되지 않음)
System.out.println(arr1 == arr3);        // true

// 참조 타입의 특징 - 한 배열 수정 시 참조하는 모든 변수에 영향
arr3[0] = 10;
System.out.println(arr1[0]); // 10 - arr1도 변경됨

배열 내용 비교하는 올바른 방법

import java.util.Arrays;

int[] arr1 = {1, 2, 3};
int[] arr2 = {1, 2, 3};
System.out.println(Arrays.equals(arr1, arr2)); // true - 내용 비교

6. 주의사항 및 팁

자주 하는 실수들

  1. 참조 타입을 == 으로 내용 비교

    String str1 = new String("test");
    String str2 = new String("test");
    if (str1 == str2) {  // 잘못된 비교!
        // 실행되지 않음
    }
  2. null 체크 없이 equals() 사용

    String str = null;
    // str.equals("test");  // NullPointerException 발생!
    
    // 올바른 방법
    if (str != null && str.equals("test")) {
        // 안전한 비교
    }
    
    // 더 안전한 방법
    if ("test".equals(str)) {
        // 상수를 앞에 두어 null 예외 방지
    }

효과적인 활용 팁

  1. 문자열 비교는 항상 equals() 사용
  2. 객체 참조 동일성 확인이 필요할 때만 == 사용
  3. 배열 내용 비교 시 Arrays.equals() 활용
  4. null 체크를 습관화

7. 마무리

참조 타입의 == 연산과 equals() 메소드의 차이를 이해하는 것은 Java 프로그래밍의 기본임.

핵심은 == 연산자는 변수에 저장된 값 자체를 비교한다는 점임. 기본 타입에서는 실제 값이, 참조 타입에서는 메모리 주소가 비교됨.

객체의 내용을 비교하려면 반드시 equals() 메소드를 사용해야 하며, 특히 String은 리터럴 생성 방식에 따라 == 연산 결과가 달라질 수 있음을 주의해야 함.

이 개념을 확실히 이해하면 참조 타입 관련 버그를 예방하고 더 안정적인 코드를 작성할 수 있음.

0개의 댓글