세로형
Recent Posts
Recent Comments
Link
04-23 14:36
«   2024/04   »
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 29 30
Archives
Today
Total
관리 메뉴

꿈 많은 사람의 이야기

자바 Object 클래스(equals, hashCode, toString 메소드) 본문

java

자바 Object 클래스(equals, hashCode, toString 메소드)

이수진의 블로그 2017. 8. 17. 08:59

클래스를 선언할 때 extends키워드로 다른 클래스를 상속하지 않으면 암시적으로 java.lang.Object 클래스를 상속하게 된다.
즉, 모든 클래스는 Object 클래스의 자식이거나 자손 클래스이다. Object 클래스는 자바의 최상위 부모 클래스이다.

Object 클래스에는 다양한 메소드가 있다. 대표적인게 equals()메소드, hashCode(), toString() 메소드이다.

equals() 메소드


equals메소드는 public boolean equals(Object obj) 형태로 되어있다.
매개 타입이 Object인 것은 모든 객체가 매개값으로 대입될 수 있음을 말한다. Object의 equals()메소드는 두 객체가 동일한 객체라면 true를 리턴하고 그렇지 않으면 false를 리턴한다.

자바에서는 두 객체를 동등 비교할 때 equals()메소드를 흔히 사용한다. equals()메소드는 객채가 동등하면 true, 다르면 false를 리턴하는데 이때 동등의 조건은 객체가 저장하고 있는 데이터가 동일함을 뜻한다. (객체가 같건, 다르건간은 상관하지 않는다)

예를 들어 String 클래스의 equals()메소드는 문자열의 값을 보고 객체의 번지를 비교하는게 아니라 그 값이 동등하면 true를 리턴한다. 이것은 String 클래스가 Object 클래스의 equals() 메소드를 오버라이딩해서 번지 비교가 아닌 문자열 비교로 변경했기 때문이다.

equals 메소드를 재정의할 때에는 매개값(비교 객체)이 기준 객체와 동일한 타입의 객체인지 확인해야 한다. 이것을 확인하는 방법은 
instanceof 연산자를 이용하면 된다. 만약 비교 객체가 다르면 false를 리턴해야 한다. 객체가 같으면 기준 타입으로 형변환해서 필드 값이 같나 비교해야 한다. 
말로 하면 어려우니 소스를 봐보자

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class Member{
    String id;
    public Member(String id)
    {
        this.id = id;
    }
    
    public boolean equals(Object obj)
    {
        if(obj instanceof Member)
        {
            Member member = (Member) obj;
            if(id.equals(member.id)){
                return true;
            }
        }
        return false;
    }
}
 
 
 
public class MemberExample {
 
    public static void main(String[] args) {
        Member obj1 = new Member("blue");
        Member obj2 = new Member("blue");
        Member obj3 = new Member("red");
 
        if(obj1.equals(obj2))
        {
            System.out.println("obj1과 2는 같습니다.");
        }
        else
        {
            System.out.println("obj1과 2는 다릅니다.");
        }
        if(obj1.equals(obj3))
        {
            System.out.println("obj1과 3은 같습니다.");
        }
        else
        {
            System.out.println("obj1과 3은 다릅니다.");
        }
    }
    
}
Colored by Color Scripter

Member 클래스는 equals() 메소드를 오버라이딩 했다. 먼저 객체 타입이 동일한지 instanceof 연산자로 확인한다. 타입이 다르면 false이다.
타입이 같으면 매개 값으로 들어온 값을 기준 객체 타입(Member)으로 강제 타입 변환한다. 그리고 해당 필드 값을 비교해 같으면 true를 반환한다.

이렇게 Object 클래스의 equals() 메소드는 오버라이딩하여 사용할 수 있다.

hashCode() 메소드


hashCode()메소드는 Object 클래스에서 있는 대표적인 메소드 중 하나이다. 객체 해시코드란 객체를 식별할 하나의 정수값을 말한다. Object의 hashCode() 메소드는 객체의 메모리 번지를 이용해서 해시코드를 만들어 리턴하기 때문에 객체마다 다른 값을 가지고 있다.

추후에 나오는 클렉션 플레임워크에서 HashSet, HashMap, Hashtable은 먼저 hashCode()를 실행해서 해시코드 값이 같은지 보고 다르면 다른객체로 판한한다. 같으면 equals()메소드로 다시 비교하여 같은지 비교한다.
hashCode가 같아도 equals가 false면 다른 객체이다.

그림으로 보면 다음과 같다

 

 



다음 예제를 보면서 더 알아보자

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
29
30
31
32
33
class Key{
    public int number;
    
    public Key(int number){
        this.number = number;
    }
    
    public boolean equals(Object obj)
    {
        if(obj instanceof Key)
        {
            Key compKey = (Key) obj;
            if(this.number == compKey.number)
                return true;
        }
        return false;
    }
}
 
 
public class KeyExample {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        HashMap<Key, String> hm = new HashMap<Key, String>();
        hm.put(new Key(1), "홍길동");
        String value = hm.get(new Key(1));  //-> null이 
        System.out.println(value);
    }
 
}
 
 
Colored by Color Scripter

위 소스에서는 hashCode( ) 메소드를 재정의하지 않았기 때문에 Object의 hashCode()메소드가 사용된다.
이렇게 하면 올바른 값을 찾아오지 못한다. 왜나햐면 number 필드 값이 같더라도 hashCode() 메소드에서 리턴하는 해시코드가 다르기 때문에 다른 식별키로 인식하기 때문이다.

이것을 해결하려면 hashCode()를 오버라이딩하여 number를 비교하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Key{
    public int number;
    
    public Key(int number){
        this.number = number;
    }
    
    public boolean equals(Object obj)
    {
        if(obj instanceof Key)
        {
            Key compKey = (Key) obj;
            if(this.number == compKey.number)
                return true;
        }
        return false;
    }
    
    public int hashCode(){
        return number;
    }
}
Colored by Color Scripter

오버라이딩 한 소스는 위와 같다.

toString() 메소드

Object 클래스의 toString() 메소드는 객체의 문자 정보를 리턴한다. 객체의 문자 정보란 객체를 문자열로 표현한 값을 말한다. 기본적으로 Object 클래스의 toString() 메소드는 "클래스명@16진수해시코드"로 구성된 문자 정보를 리턴한다.
일반적인 리턴 값은 잘 쓰이지 않으며 이 메소드를 오버라이딩해서 유익한 정보를 리턴하도록 쓰인다. 다음 예제를 보자

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
class SmartPhone{
    private String company;
    private String os;
    
    public SmartPhone(String company, String os)
    {
        this.company = company;
        this.os = os;
    }
    
    public String toString()
    {
        return company+", "+os;
    }
}
 
public class SmartPhoneExample {
 
    public static void main(String[] args) {
        SmartPhone s1 = new SmartPhone("samsung","android");
        SmartPhone s2 = new SmartPhone("google","android");
        System.out.println(s1.toString());
        System.out.println(s2.toString());
 
    }
 
}
Colored by Color Scripter


SmartPhone클래스는 toString() 메소드를 오버라이딩 했다. 메인에선 SmartPhone 클래스 객체를 생성해서 값을 넣어준다. 그리고 출력문에서 해당 객체.toString()을 하면 toString() 메소드가 호출 되는데 toString() 메소드는 company+", "+os;를  문자열로 만들어 리턴해준다.

이런식으로 toString() 메소드를 오버라이딩 해서 사용할 수 있다.


반응형
그리드형
Comments