java.lang패키지

 

equals


예제

public static void main(String[] args) {
    Value v1 = new Value(10);
    Value v2 = new Value(20);
    System.out.println("test");


    if (v1.equals(v2)) {
        System.out.println("같음");
    }
    else {
        System.out.println("다름");
    }

    v2 = v1;
    if (v1.equals(v2)) {
        System.out.println("두번째 같음");
    }
    else {
        System.out.println("두번째 다름");
    }
}

equals메서드는 객체의 주소의 일치여부를 보는 메서드이다.

따라서 첫번째는 객체의 주소가 다름으로 "다름"이 출력되고

 

두번째는 v2 = v1을 통해 같은 객체의 주소를 가르키고있음으로 "두번째 같음"이 출력된다.

 

 

예제2

Person p1 = new Person(8011);
        Person p2 = new Person(8011);

        if (p1==p2) {
            System.out.println("같음");
        }
        else {
            System.out.println("다름");
        }
        if (p1.equals(p2)) {
            System.out.println("두번째 같음");
        }

    }
}
class Person {
    long id;

    public boolean equals(Object obj) {
        if (obj instanceof Person) {
            return id == ((Person)obj).id;
        }
        else {
            return false;
        }
    }
    Person(long id) {
        this.id =id;
    }
}

 

 

두번째 예제는 객체의 주소값이 아닌 객체의 값을 비교하기위해 equals를 오버라이딩 한것이다.

return id == ((person)obj).id ; 는 obj가 조상클래스이기 때문에 id를 참조하기 위해서는 Person타입으로 형변환이 필요해서 하였다.

 

출력결과는 다름 , 두번째 같음  이 출력된다.

 

 

hashCode()


해시함수는 찾고자하는 값을 입력하면 그 값이 저장된 위치를 알려주는 해시코드를 반환한다. 

같은 객체라면 hashCode를 호출하였을 때 결과값인 해시코드고 같아야한다.

 

예제

String str1 = new String("abc");
    String str2 = new String("abc");
    System.out.println(str1.equals(str2));
    System.out.println(str1.hashCode());
    System.out.println(str2.hashCode());
    System.out.println(System.identityHashCode(str1));
    System.out.println(System.identityHashCode(str2));
}

String 클래스는 문자열의 내용이 같으면 동일한 해시코드를 반환하도록 hashCode메서드에 오버라이딩 되어있어서

true , str1, str2 모두 동일한 해시코드가 반환된다.

 

반면 System.identity는 객체의 주소값으로 해시코드를 생성해 항상 다른 해시코드값을 반환한다.

따라서 str1 과 str2는 해시코드는 같지만 다른 객체이다.

 

toString()


인스턴스에 대한 정보를 문자열로 제공해주는 메서드이다.

public static void main(String[] args) {
    int[] arr = {1,2,3};
    int num = 1;
    System.out.println(arr.toString());

출력 : [I@2d98a335

 

toString() 메서드는 오버라이딩이 가능하다.

 Card c1 = new Card();
        System.out.println(c1.toString());
    }
}
class Card {
    int number =2;

    public String toString() {
        return "number = " + number;
    }

}

출력 : number = 2

 

clone()


clone은 자신을 복제하여 새로운 인스턴스를 생성한다. 

Object클래스에 clonew은 인스턴스변수의 값만 복사하여 참조타입의 인스턴스 변수는 완전히 복제가 이루어지지않는다.

이렇기 때문에 clone 메서드를 오버라이딩 할 필요가 있다.

 

방법

example p1 = new example(3,5);
    example p2 = (example)p1.clone();  //Object클래스와 example클래스이기 때문에 형변환 필요
    }
}

class example implements Cloneable { //clonealbe이 있어야지만 clone을 쓸수있다. 없으면 예외가 발생
    int x ,y
    example(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public String toString() {
        return x + " " + y;
    }
    protected Object clone() {  //protected말고 public 을 쓰면 상속관계가 아니여도 사용가능하다.
        Object obj = null;
        try {
            obj = super.clone(); //Object에 있는 클론  클론은 예외처리 필수 
        } catch (CloneNotSupportedException e) {}
        return obj;
    }
    
     }

 

공변반환타입: 조상메서드의 반환타입을 자손 클래스

public example clone() {
    Object obj = null;
    try {
        obj = super.clone();
    } catch (CloneNotSupportedException e){}
    return (example)obj;
}

의 타입으로 변경가능한것   - 반환을 클래스 타입으로 반환한다.

 

clone의 문제


복제에는 얕은 복사와 깊은 복사가 존재한다. 

얕은복사 =  객체가 참조하는 객체까지는 참조하지않는다. 원본과 복제본이 같은 객체 공유

깊은 복사 = 원본과 복제본이 다른 객체를 참조. good

 

앝은복사

example코드는 위에

 int [] arr = {1,2,3};
    arrTest t1 = new arrTest(arr,new example(7,8));
    arrTest t2 = t1.shallowCopy();
    t2.e.x=10;
    t2.x[1] = 10;
        System.out.println(t1);
        System.out.println(t2);
    }
}
class arrTest  implements  Cloneable{
    int[] x;
    example e;
    arrTest(int[] x,example e) {
        this.x = x;
        this.e = e;
    }
    public String toString() {
        return Arrays.toString(x) + e;
    }
    public arrTest shallowCopy() {
        Object obj = null;
        try {
            obj = super.clone();
        } catch (CloneNotSupportedException e){}
        return (arrTest) obj;
    }
}

얕은 복사로인해 복사본을 변경했음에도 불구하고 원본까지 변경이됨.(같은 인스턴스를 가르키고있기때문에)

 

깊은복사

 int [] arr = {1,2,3};
    arrTest t1 = new arrTest(arr,new example(7,8));
    arrTest t2 = t1.shallowCopy();
    arrTest t3 = t1.deepCopy();
    t2.e.x=10;
    t2.x[1] = 10;
        System.out.println(t1);
        System.out.println(t2);
        System.out.println(t3);
    }
}
class arrTest  implements  Cloneable{
    int[] x;
    example e;
    arrTest(int[] x,example e) {
        this.x = x;
        this.e = e;
    }
    public String toString() {
        return Arrays.toString(x) + e;
    }
    public arrTest shallowCopy() {
        Object obj = null;
        try {
            obj = super.clone();
        } catch (CloneNotSupportedException e){}
        return (arrTest) obj;
    }
    public arrTest deepCopy() {
        Object obj = null;
        try {
            obj = super.clone();
        } catch (CloneNotSupportedException e){}
        arrTest at = (arrTest) obj; //새롭게 인스턴스를 하나 생성
        at.e = new example(this.e.x,this.e.y); //생성한 객체의 값을 지정
        return at;
    }
}

깊은 복사로 복사한 example 객체의 값은 변경해도 바뀌지않는다.  -> copy는 원본 객체가 가지고 있는 값만 그대로 복사

deepcopy = 원본이 참조하고 있는 객체까지 복사!!!!

 

 

+ Recent posts