Search

반응형

'equals()'에 해당되는 글 1건

  1. 2020.04.09 [java]비교연산 "==" vs "equals()" 쉽게 이해하기.
반응형

안녕하세요~ 신기한연구소 티보이입니다.

자바(java) 개발 중 값을 비교해야 하는 경우가 종종 있습니다.

보통 숫자는 비교 연산자인 "=="로 문자열은 문자열 비교 메서드인 equals()를 주로 사용하는데 왜 문자열은 비교 연산자인 "=="를 사용하면 다르게 나오는지 같이 확인해 보겠습니다.

1. 비교연산자 (==)

비교 연산자(==)는 변수의 데이터가 저장된 메모리 위치(해시코드)를 비교합니다.

다음 예를 살펴볼게요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
        // 샘플 1
        long long1 = 32L;
        long long2 = 32L;
        
        System.out.println(long1);
        System.out.println(long2);
        System.out.println(System.identityHashCode(long1));
        System.out.println(System.identityHashCode(long2));
        
        
        System.out.println((long1 == long2?"same value" : "diff value")); //결과1
        
        //샘플 2
        String s1 = "te";
        String s2 = "st";
        String s3 = s1 + s2;
        String s4 = "test";
        String s5 = "test";
        
        System.out.println(s3);
        System.out.println(s4);
        System.out.println(s5);
        System.out.println(System.identityHashCode(s3));
        System.out.println(System.identityHashCode(s4));
        System.out.println(System.identityHashCode(s5));
        
        System.out.println((s3 == s4?"same value" : "diff value")); //결과2
        System.out.println((s4 == s5?"same value" : "diff value"));  //결과3
cs

결과 :

32
32
366712642
366712642
same value
test
test
test
1829164700
2018699554
2018699554
diff value
same value

우선 샘플 1을 보면 기본형 long 변수인 long1, long2를 32L 값으로 할당했습니다.

두 값을 비교 연산자인 '=='를 사용한 결과1을 보시면 'same value'가 출력되었습니다.

값은 둘 다 32를 출력했고 해시코드(hashcode)도 동일한 '366712642'값을 출력했습니다.

메모리 위치를 나타내는 해시코드가 같음을 알 수 있습니다.

비교 연산자는 이 해시코드 값을 비교합니다.

샘플 2를 보시면 문자열 비교를 합니다.

S4와 S5 둘 다 'test' 값이 할당되어 있습니다.

결과3에서 비교 연산자를 사용해서 비교해 보면 'same value'로 나옵니다.

두 변수 S4와 S5의 해시코드 값도 '2018699554'로 동일합니다.

그런데 S3와 S4를 보면 값은 둘 다 'test'인데 결과2를 보면 'diff value'로 표출됩니다.

비교 연산자는 이 두 개의 값을 다르게 인식합니다.

두 값의 해시코드를 보면 S3 (1829164700)와 S4 (2018699554)로 서로 다름을 알 수 있습니다.

왜 다르게 나오냐면 S3의 경우 S1과 S2의 결합으로 비록 값은 같지만 새로운 메모리에 객체로 생성되기 때문입니다.

결국 비교 연산자는 눈에 보이는 값으로 비교하는 게 아닌 변수의 값이 저장된 해시코드값으로 비교한다는 것을 확인할 수 있습니다.

효율적인 메모리 사용을 위해 변수에 값을 할당할 때 기존에 같은 값이 있으면 같은 해시코드로 지정됩니다.

2. equals() 메서드로 비교하기

우선 이 메서드는 기본형(primitive type)에서는 사용할 수 없습니다.

이유는 equals()는 객체에서 호출되는 메서드인데 기본형 타입은 객체가 아니라 변수이기 때문입니다.

쩜 찍어보면 아무것도 안 나오거든요. ㅎㅎ

equals() 메서드의 예를 살펴보겠습니다.

1
2
3
4
5
6
7
8
9
//샘플 3
        String s1 = "te";
        String s2 = "st";
        String s3 = s1 + s2;
        String s4 = "test";
        String s5 = "test";
        
        System.out.println((s3.equals(s4)?"same value" : "diff value")); //결과4
        System.out.println((s4.equals(s5)?"same value" : "diff value")); //결과5
cs

위 예제의 결과4와 결과5는 둘 다 'same value'가 나옵니다. 비교 연산자와 다른 결과가 나왔습니다.

그 이유는 equals() 메서드는 두 변수의 메모리(해시코드)에는 관심이 없고 단지 눈에 보이는 글자 그 자체를 비교하기 때문입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
        Long rLong1 = new Long(32L);
        Long rLong2 = rLong1;
        Long rLong3 = new Long(rLong1);
        Long rLong4 = new Long(32L);
        
        
        System.out.println(System.identityHashCode(rLong1));
        System.out.println(System.identityHashCode(rLong2));
        System.out.println(System.identityHashCode(rLong3));
        System.out.println(System.identityHashCode(rLong4));
        
        System.out.println((rLong1.equals(rLong2)?"same value" : "diff value")); //결과6
        System.out.println((rLong1.equals(rLong3)?"same value" : "diff value")); //결과7
        System.out.println((rLong1.equals(rLong4)?"same value" : "diff value")); //결과8
        System.out.println((rLong3.equals(rLong4)?"same value" : "diff value")); //결과9
        
        
        System.out.println((rLong1 == rLong2?"same value" : "diff value")); //결과10
        System.out.println((rLong1 == rLong3?"same value" : "diff value"));  //결과11        
        System.out.println((rLong1 == rLong4?"same value" : "diff value"));  //결과12    
        System.out.println((rLong3 == rLong4?"same value" : "diff value"));  //결과13
cs

위 예제에서는 Long 객체를 생성해서 '=='와 'equals()'로 비교를 해봤습니다.

이제 어떤 결과가 나올지 예측이 되시나요?

결과6은 equals()를 사용했기에 값 자체만 비교하므로 'same value'가 나옵니다.

결과7, 결과8, 결과9도 'same value'가 나옵니다.

 

결과10은 rLong1객체를 rLong2에 대입시켰기 때문에 같은 해시코드를 갖게 됩니다. 그래서 'same value'가 나오게 됩니다.

결과 11부터 13까지는 새로운 객체를 생성했기에 눈에 보이는 값은 32로 같지만 다른 해시코드를 갖고 있기에 'diff value'가 나옵니다.

3. 결론

같은 메모리 위치를 참조하는지 확인하기 위해서는 비교 연산자 == 를 사용하면 됩니다.

아래 예와 같이 long1과 long2는 32L 을 할당받게 됩니다. long2의 값이 long1과 같기에 굳이 새로운 메모리에 똑같은 값을 넣고 메모리를 차지할 이유가 없기 때문입니다. 효율적인 자바네요. ㅎㅎ

이런 경우는 비교 연산자 ==로 비교 시 같다고 나옵니다.

하지만 아래와 같이 새로운 객체(참조형 변수)를 만들게 되면 값은 중요하지 않습니다. 새로운 놈이 나타난 것이기 때문에 값이 같더라도 새로운 위치를 하나 내어줍니다.

그래서 long1과 long2의 값이 32L로 같더라도 new로 새로운 객체로 만들어졌기 때문에 해시코드값도 다르게 됩니다.

해시코드값(메모리 위치)이 같은지 비교할 때는 비교 연산자 (==)를 사용하고

해시코드값이 달라도 글자 그 자체를 비교할 때는 equals()메소드를 사용하면 됩니다.

즐 코딩하세요~

반응형