java.lang.*;
프로그래밍 시 import하지 않아도 자동으로 추가가 되며 많이 사용하는 기본 클래스들이 속한 패키지이다.
하위 클래스로는 Object 클래스가 있다.
모든 클래스의 최상위 클래스이다.
모든 클래스는 Object 클래스를 상속받으며 구현된 메소드들을 전부 사용 가능하다.
모든 클래스는 Object 클래스의 메서드 중 일부 메서드를 재정의할 수 있다. (final로 선언된 메서드 제외)
하지만, Object 클래스를 상속 받았다는 것을 표현하지 않고도 Object 클래스의 메서드를 이용할 수 있다.
class Student{
int studentID;
String studentName;
}
왜냐하면, 컴파일러가 자동으로 extends Object를 추가해주기 때문이다.
class Student extends Objects{
int studentID;
String studentName;
}
우리가 자주 쓰는 Object 클래스의 메서드에 대해 알아보자.
class Student2{
int StudentID;
String StudentName;
public Student2(int studentID, String studentName) {
StudentID = studentID;
StudentName = studentName;
}
}
public class ToStringEx2 {
public static void main(String[] args) {
Student2 student2 = new Student2(20194440, "은비");
System.out.println(student2);
}
}
section3.object.Student2@7a81197d
toString() 메서드를 재정의하지 않을 경우 이렇게 자신의 주소값을 반환한다. 그렇다면 toString 메서드를 재정의해보자.
Student2 클래스 내부에서 cmd+n을 누르면 이렇게 친절하게 Object의 메서드들을 바로 재정의할 수 있다.
@Override
public String toString() {
return "Student2{" +
"StudentID=" + StudentID +
", StudentName='" + StudentName + '\'' +
'}';
}
inteliJ가 이렇게 자동으로 오버라이딩 해준다.
Student2{StudentID=20194440, StudentName='은비'}
아까의 주소값이 아닌, 재정의한대로 결과가 나왔다.
String str = new String("test");
System.out.println(str);
test
하지만, String 클래스의 경우 toString을 재정의하지 않아도 주소값이 아닌 test를 출력한다. 그 이유는 바로 String 클래스에 이미 toString이 재정의되어 있기 때문이다.
public class EqualsEx2 {
public static void main(String[] args) {
String str1 = new String("test");
String str2 = new String("test");
System.out.println(str1 == str2);
}
}
String 인스턴스를 생성하고 같은 값인지 확인해보자.
false
이 둘은 논리적으로 같은 값이나 물리적으로 다른 주소 값을 가지기 때문에 결과는 false가 나온다.
System.out.println(System.identityHashCode(str1));
System.out.println(System.identityHashCode(str2));
918221580
2055281021
System.identityHashCode를 이용하여 주소값을 확인하니 역시 다르게 저장되어 있다.
class Member{
int memberID;
String memberName;
public Member(int memberID, String memberName) {
this.memberID = memberID;
this.memberName = memberName;
}
}
public class EqualsEx2 {
public static void main(String[] args) {
String str1 = new String("test");
String str2 = new String("test");
System.out.println(str1 == str2);
System.out.println(System.identityHashCode(str1));
System.out.println(System.identityHashCode(str2));
Member member1 = new Member(2001,"eunbi");
Member member2 = new Member(2001,"eunbi");
System.out.println(member1==member2);
System.out.println(System.identityHashCode(member1));
System.out.println(System.identityHashCode(member2));
}
}
직접 Member 클래스를 생성해서 위와 같이 다시 확인해보자.
false
918221580
2055281021
false
617901222
1159190947
역시나 결과는 이렇다. 그러면 Member 클래스에 equals 메서드를 재정의해보자.
아까와 같이 command+n을 누르고 추가하면 된다.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Member member = (Member) o;
return memberID == member.memberID && Objects.equals(memberName, member.memberName);
}
@Override
public int hashCode() {
return Objects.hash(memberID, memberName);
}
위와 마찬가지로 Member 클래스에 오버라이딩되었다. 역시나 편한 inteliJ
public class EqualsEx2 {
public static void main(String[] args) {
Member member1 = new Member(2001, "eunbi");
Member member2 = new Member(2001, "eunbi");
System.out.println(member1.equals(member2));
System.out.println(System.identityHashCode(member1));
System.out.println(System.identityHashCode(member2));
System.out.println(member1.hashCode());
System.out.println(member2.hashCode());
}
}
true
2055281021
1554547125
96933013
96933013
equals 메서드로 논리적으로 같음을 정의하고, System.identityHashCode로 확인해본 결과 원래 다른 주소값에 저장되어 있던, 즉 물리적으로 다른 값이였던 두 인스턴스가 hashCode() 메서드를 이용하여 같은 물리적 주소값이 반환된 것을 확인할 수 있다.
class Point{
int x;
int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "Point{" +
"x=" + x +
", y=" + y +
'}';
}
}
class Circle implements Cloneable {
Point point;
private int radius;
public Circle(int x, int y, int radius) {
point = new Point(x,y);
this.radius = radius;
}
@Override
public String toString() {
return "Circle{" +
"point=" + point +
", radius=" + radius +
'}';
}
// 반환형이 오브젝트
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class CloneEx {
// clone할 수 없을 때 예외처리가 생김 일단 throws 처리
public static void main(String[] args) throws CloneNotSupportedException {
Circle circle = new Circle(10,20,5);
Circle cloneCircle = (Circle)circle.clone();
System.out.println(System.identityHashCode(circle));
System.out.println(System.identityHashCode(cloneCircle));
System.out.println(circle);
System.out.println(cloneCircle);
}
}