모든 클래스의 최고 조상. 오직 11개의 메서드만을 가지고 있다.
-notify(), wait()등은 쓰레드와 관련된 메서드이다.
-equlas(), hashCode(), toString()은 적절히 오버라이딩해야한다.
-모든클래스는 Object클래스의 메서드를 사용가능하고 그중 일부는 재정의 하여 사용할수가 있다.
-위치는 java.lang.Object 클래스 입니다.
객체의 정보를 문자열(String)로 제공할 목적으로 정의된 메서드
public class Book {
public String title; //제목
public String author; //저자
public Book(){} //디폴트 생성자
public Book(String title, String author) { //생성자(title,author)
this.title = title;
this.author = author;
}
@Override
public String toString() { //toString재정의
return author + "," + title;
}
}
public class ToString {
public static void main(String[] args) {
Book book = new Book("토지","박경리");
System.out.println(book); //내용물이 출력되는 것이아닌 인스턴스의 주소값이 출력
String str = new String("토지");
System.out.println(str.toString());
}
}
Object클래스의 메서드인 ToString을 예제로 사용해보겠습니다. ToString클래스를 만들면 모든 클래스는 Object를 상속하기 때문에 ToString클래스 또한 Object에 메서드를 사용할 수 있습니다.
이후 Book클래스를 작성하여 인스턴스를 생성시 title,author을 입력할 수 있게 한뒤, 다시main메서드로 돌아와 Book인스턴스를 생성하여 "토지","박경리"를 입력합니다.
그 후 출력문으로 book을 출력하면 내용물이 출력되는 것이아닌 인스턴스의 주소값이 출력됩니다.
하지만 String인스턴스를 생성하여 입력하여 str을 출력하면 바로 토지가 출력되는데, 그것은 String이 출력될때 자동으로 toString메서드를 사용하게 되어있기 때문입니다.
Book에서도 자동으로 toString()을 하기 위해 Book클래스에 toString메서드를 재정의하고
authoer + "," + title순으로 출력하게 하고 다시 book을 출력해보면 "토지","박경리"라고 출력되게 됩니다.
이것을 통해서 모든 클래스에서 Object클래스의 메서드를 사용할 수 있고 또한 필요에 따라 메서드를 재정의해서 사용할 수 있는 것을 알 수 있습니다.
equals()메서드는 두 객체의 동일함을 논리적으로 재정의하는 메서드입니다.여기서 논리적 동일함은 서로 주소는 다르지만, 같은 값을 가지는 객체를 뜻하고 서로 같은 주소를 가지는 물리적 동일함과 다른의미로 사용된다.정리해보면 equals()는 물리적으로 다른 메모리에 위치한 객체라도 논리적으로 동일함을 구현하기 위해 사용되는 메서드.
public class EqualsTest {
public static void main(String[] args) {
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1 == str2);//두 인스턴스는 다른 주소에 있기 때문에 false
System.out.println(str1.equals(str2));//값이 같냐?주소는 달라도되.논리적 동일성
}
}
public class Student {
public int studentNum;
public String studentName;
public Student(int studentNum, String studentName) {
this.studentNum = studentNum;
this.studentName = studentName;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Student) { //참조변수 obj, 타입(클래스명)Student(피연산자)
Student std = (Student) obj; //Object클래스로 업캐스팅된것을 다운캐스팅
return (this.studentNum == std.studentNum);
}
return false;
}
}
//Object obj = new Student //업캐스팅. obj는 스튜턴트 객체를 가지지만,object의 멤버,변수만쓸수있다.
//Student student =(Student)obj //다운 캐스팅. student는 다쓸수 있다.
//if(obj instanceof Student)
class EqualTest{
public static void main(String[] args) {
Student Lee = new Student(100,"이순신");
Student Lee2 = Lee;
Student Shin = new Student(100,"이순신");
System.out.println(Lee == Lee2); //true
System.out.println(Lee == Shin); //false
System.out.println(Lee.equals(Shin)); //재정의전//false
System.out.println(Lee.equals(Shin)); //재정의후 //true
}
}
Lee와 Lee2는 물리적으로 같은 주소를 가지고 있기 때문에 Lee=Lee2는 true가 반환됩니다.
Lee와 shin는 물리적으로 같지 않기 때문에 Lee == shin 는false가 반환됩니다.
Lee.equals(shin) equlas 재정의 전에는 비교할 항목이 지정이 안되있기 때문에 false가 발생합니다
Book 클래스로 돌아가서 equals 메서드를 재정의합니다. 메서드에서 사용될 때 비교되는 항목이 자동으로
Object로 업캐스팅 되기 때문에 instanceof를 사용해서 안전하게 Student클래스로 다시 다운캐스팅하고 두 항목의 studentNum을 비교하게 재정의합니다
다시 Lee.equals(shin)을 하게되면 true가 반환됩니다.
hashCode()메서드의 반환값은 10진수의 인스턴스가 저장된 가삼머신의 주소입니다.
System.out.println(Lee); //object.Student@79fc0f2f
System.out.println(Lee.hashCode()); // 2046562095
System.out.println(shin.hashCode()); // 1342443276
기본 주소값이 가진 16진수인 것과 다르게 hashCode()를 사용하면 10진수 주소를 반환해 줍니다.
두개의 서로 다른 메모리에 위치한 인스턴스가 동일하다는 것은 equals()의 반환값이 true여서 논리적으로 동일함을 보여주고 또한 동일한 hashCode값을 가져야 합니다.
위의 Lee 와 Shin은 equals()의 반환값은 true이지만 hashCode의 값은 다른 모습을 보여주고 있는데 이는 hashCode는 재정의 하지 않았기 때문이빈다.이러한 이유로 equals()를 재정의할 때 hashCode()를 같이 재정의해주는 경우가 많습니다.
참고로 hashCode가 같아 지게 재정의한다고 해서 실제 hashCode 주소값이 같다는 뜻은 아닙니다.
public class Student {
public int studentNum;
public String studentName;
public Student(int studentNum, String studentName) {
this.studentNum = studentNum;
this.studentName = studentName;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof JavaStandard9.equals.Student) { //참조변수 obj, 타입(클래스명)Student(피연산자)
Student std = (Student) obj; //Object클래스로 업캐스팅된것을 다운캐스팅
return (this.studentName == std.studentName);
}
return false;
}
@Override
public int hashCode() {
return studentNum;
}
}
public class HashCodeTest {
public static void main(String[] args) {
Student Lee = new Student(100, "이순신");
Student Shin = new Student(100, "이순신");
System.out.println(Lee.hashCode()); // 100
System.out.println(Shin.hashCode()); // 100
//hashCode 는 Student 클래스에서 studenNum을로 재정의 했다.
System.out.println(System.identityHashCode(Lee)); //423031029
System.out.println(System.identityHashCode(Shin)); //1712669532
// hascode()값이 궁금하다면 System.identityHashCode()메서드를 사용
}
}
hashCode를 재정의하여 Lee와 Shin에 hascCode()를 같게 만들려고 할 때 return값은 equals를 재정의 할때 썻던 멤버 변수를 사용하는게 좋습니다.
그래서 return을 equals에서 기준이 되었던 studentNum을 사용하면 Lee와 Shin의 hashCOde()값이 100으로 같아지는 것을 확인할 수 있습니다.
만약 진짜 hashCode()값이 궁금하다면 System.identityHashCode()메서드를 사용하면 된#다.
clone()메서드는 객체의 복사본을 만드는 메서드로 기본틀(protopype)이 되는 객체로부터 같은 속성 값을 가진 복사본을 생성할 수 있는 메서드입니다.
-객체지향 프로그래밍의 정보은닉에 위배되는 가능성이 있으므로 복사할 객체는 clonable 인터페이스를 명시해야 한다.
public class Book implements Cloneable{
//클론메서드를 추가하기 위해 클래스 선언부에 복사가 가능하다는 의미로 implements Clonable을 붙여준다.
public String title;
public String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
@Override
public String toString() {
return author + "," + title;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
//클론 메서드를 재정의하는데 따로 수정할 것은 없고 그대로 가져다 쓰면 됩니다.
}
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException{
Book book = new Book("토지","박경리");
System.out.println(book); //박경리, 토지
Book book2 =(Book)book.clone();
//book의 복사본을 만들기 위해 book2에 book.clone()메서드를 사용해주고 앞에 (Book)타입을 명시해준다.
System.out.println(book2); //박경리, 토지
}
}