CS지식들/공부공부

Object (Java)

솜사탕코튼 2023. 11. 5. 15:58

Object 

  • 모든 클래스의 조상
  • 필드 없이 메소드들만 갖고 있음
    • 모든 클래스들에 상속됨
    • 필요에 따라 오버라이드하여 사용

 

 

 

toString()

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
  
  
@HotSpotIntrinsicCandidate
public final native Class<?> getClass();
    
public String getName() {
    String name = this.name;
    if (name == null)
        this.name = name = getName0();
    return name;
}
  • 클래스명과 해시값을 반환
  • toString을 Override하지 않으면
  • java.lang.Object@59e84876 이런식으로 나오게 됨

 

class Button {
	private String name;
}
// 사실은 이런 상태
class Button extends Object {
	private String name;
    // 재정의 해서 사용할 수 있음
    @Override
    public String toString() {
    	System.out.println("버튼의 이름은 " + name + " 이다"); 
    }
}

 

equals(Object obj)

public boolean equals(Object obj) {
    return (this == obj);
}

 

@Override
public boolean equals(Object o) {
	if (this == o) return true;
	if (o == null || getClass() != o.getClass()) return false;
	Click click = (Click) o;
	return x == click.x && x == click.y;
}
  • 재정의해서 사용
  • 무슨 차이인지 생각해보면, 보통은 주소값을 비교해서 같은 타입의 객체이고, 그 안의 내용이 같아도 두 객체는 다르다고 나오게된다.(equals를 override하지 않았을 경우)

 

hashCode()

@HotSpotIntrinsicCandidate
public native int hashCode();
  • 기본적으로는 각 인스턴스 고유의 메모리 위치값을 정수로 반환
  • 이해가 잘 안 갔던 점은 코드로 설명
public class Student {
    private String name;
    private int studentId;

    public Student(String name, int studentId) {
        this.name = name;
        this.studentId = studentId;
    }

    // equals 메서드를 재정의하여 이름과 학번을 기반으로 동등성을 확인
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return studentId == student.studentId &&
               Objects.equals(name, student.name);
    }
}
public static void main(String[] args) {
    Student student1 = new Student("Alice", 123);
    Student student2 = new Student("Alice", 123);

    Set<Student> studentSet = new HashSet<>();
    studentSet.add(student1);
    studentSet.add(student2);

    System.out.println("Number of students in set: " + studentSet.size()); // 2
}
  • 서로 동일한 값을 가진 객체지만, 주소값이 다르기에 Set(중복을 허용하지 않는) 의 size는 2가 된다.
@Override
public int hashCode() {
    return Objects.hash(name, studentId);
}
  • 재 정의한 후
public static void main(String[] args) {
    Student student1 = new Student("Alice", 123);
    Student student2 = new Student("Alice", 123);

    Set<Student> studentSet = new HashSet<>();
    studentSet.add(student1);
    studentSet.add(student2);

    System.out.println("Number of students in set: " + studentSet.size()); // 1
}
  • Set의 size는 1이 된다.

 

 

clone()

  • 인스턴스가 스스로를 복사하기 위해 사용
  • Cloneable 인터페이스 구현 권장
  • 깊은 복사는 직접 오버라이드하여 구현
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
public class Click {

  int x;
  int y;

  public Click(int x, int y) {
    this.x = x;
    this.y = y;
  }
}
  public static void main(String[] args) {
    Click click1 = new Click(1, 2);
    Click click2 = click1;
    click1.x = 3;
  }
  • 복사가 되었을 때 주소값을 넘겨주는 것과 같기 때문에, 깊은 복사가 되었다고 보기는 어려움.
  • 이걸 해결하기 위해 Cloneable이라는 인터페이스를 구현
  • https://7357.tistory.com/281
 

이펙티브 자바 (9) Cloneable 재정의는 주의해서 진행하라

이 글은 조슈아 블로크의 Clone 혐오가 너무 재미있어서 정리한 것이다. 따라서 저자인 조슈아 블로크가 인터뷰에서 언급한 Cloneable에 대한 의견부터, 책에 나온 단점까지 모두 열거한 뒤 본론은

7357.tistory.com