본문 바로가기

개발 관련 부가 지식/자바, 스프링

자바 객체 타입은 불변으로, 비교 방법 (공유참조, 값 복사)

728x90
728x90

자바의 객체타입과 기본타입에 = 연산 시 다른점을 정리해보고자 한다. 🤔

 

 

// 기본타입

자바의 기본타입(primitive type)  종류 

  1. byte: 8비트의 정수 타입
  2. short: 16비트의 정수 타입
  3. int: 32비트의 정수 타입
  4. long: 64비트의 정수 타입
  5. float: 32비트의 부동 소수점 타입
  6. double: 64비트의 부동 소수점 타입
  7. char: 16비트의 유니코드 문자 타입
  8. boolean: 논리 타입

-> 자바 기본 타입은 = 연산 시 값이 복사가 된다.

int a= 10;

int b = a;

b = 4 // b 값을 바꿔도 a는 10 유지

따라서, 기본타입은 값이 복사되어 서로 영향을 받지 않는다.

 

 

// 객체 타입 - 문제 파악

이제 객체타입을 보자.

public class Main {
    public static void main(String[] args) {
        StringBuilder sb1 = new StringBuilder("Hello");
        StringBuilder sb2 = sb1;

        sb2.append(", World");

        System.out.println(sb1);
        System.out.println(sb2);
    }
}

 

위와 같이 진행하였을 때, System.out.println(sb1), System.out.println(sb2) 둘 다

Hello, World 로 출력한다.

 

왜냐하면, 객체타입을 = 하는 순간, 메모리에서 객체의 위치를 가리키는 메모리 주소가 복사되어 할당되기 때문이다.

 

즉 위 코드에서 StringBuilder sb2 = sb1 하는 순간,

sb2와  sb1 은 둘 다 new StringBuilder("Hello") 라는 동일한 객체를 가리키는 주소값을 갖게 된다.

sb1과 sb2는 모두 동일한 개체를 참조하므로, sb2.append를 하여도 sb1도 반영이 되는 것이다.

 

이것을 의도하였는지는 몰라도, 같이 협업하는 프로젝트를 생각할 때에는 바람직하지 않고 큰 문제를 야기할 수 있다. 👀

 

// 객체 타입 - 문제 해결방안

따라서 객체차입을 수정할 수 없게 (불변하게) 설계 해야 한다.

-> 생성자로만 값을 설정할 것

-> set Method를 없애거나 private로 만듬

-> private final로 만듬

 

그러면 값을 바꿔야 할 때는 어떻게 할까?

->객체의 값을 바꿀 생각하지 말고 새로 만드는 것이 해결책이다. 👀

(불변으로 설계하면 바꿀 수가 없음)

 

참고.

Integer, String은 자바가 제공하는 대표적인 불변 객체이다.

 

// 기본 타입 - 비교

기본타입(primitive type)은 == 비교해도 된다.

 

// 객체 타입 - 비교

자바의 객체 비교는, 인스턴스 주소 값이 다르다고 해도 안에 든 값이 같으면 같다고 봐야한다 ❗

 

따라서, 자바의 객체 비교는 .equals()으로 동등성 비교를 해야한다

동등성 비교는 equals()를 사용해서 하는데 이때, euqals를 재정의해서 사용해야 한다.❗

재정의 하지 않을 시 기본은 == 으로 되어 있다.

 

Object equals

 

equals 재정의는 인텔리제이가 기본으로 제공해주는 기능을 사용하는 것이 좋다. ❗

 

equals 재정의 방법

(1) 클래스에서 우클릭 후 Geneate 선택

 

(2) equals() and hashCode() 선택

 

 

(3) 기본 값 그대로 Next 하면 된다.

 

 

equals 재정의 생성 모습

(생성모습은 위와 같다.)

 

👏

👏