1. 개요:
2. Object의 생성자 메서드:
빈 매개변수 생성자 하나만 가지고 있습니다. 자식 클래스들의 공통적인 특성만 부모 클래스로 추출하기 때문입니다. 자식 클래스들은 다양한 형태를 가지고 있어서 모든 자식 클래스가 공통으로 가지는 속성은 존재할 수 없습니다. 따라서 최상위 부모 클래스인 Object 클래스에는 멤버 변수가 없으며, 매개변수가 있는 생성자도 없습니다.
-> 이것이 바로 모든 클래스의 생성자 메서드 첫 줄에 숨겨진 super() 즉, 부모 클래스의 기본 생성자를 호출하는 이유입니다. 매개변수가 있는 생성자가 아닌 이유는 최상위 부모 클래스 Object 클래스에 오직 기본 생성자만 존재하기 때문입니다.
3. Object 클래스의 멤버 메서드:
1.toString 메서드: 객체의 문자열 표현을 반환
getClass().getName(): 패키지 이름과 클래스 이름을 얻을 수 있습니다;
@는 고정된 형식입니다;
Integer.toHexString(hashCode()): 객체의 주소 값을 얻을 수 있지만, 주소 값을 얻은 후에는 복잡한 연산 과정을 거쳐 16진수로 변환되어 최종적으로 얻어집니다;
toString 메서드의 결론: 기본적으로 Object 클래스의 toString 메서드는 주소 값을 반환합니다. 따라서 기본적으로 사용자 정의 객체를 출력하면 실제로는 주소 값을 출력하는 것입니다. 하지만 주소 값은 대부분 유용하지 않으므로, 주소 값을 출력하지 않으려면 최상위 부모 클래스인 Object 클래스의 toString 메서드를 재정의하여 필요한 내용을 다시 입력할 수 있습니다;
2.println 메서드:
핵심: valueOf 메서드(문자열 반환)는 다음과 같은 판단을 수행합니다. 먼저 객체가 null인지 확인하고, null이면 문자열 null을 반환하고, null이 아니면 객체로 toString 메서드를 호출합니다.
writeln 메서드: implWriteln 메서드가 있으며, textOut.write(s)는 출력이고, textOut.newLine()은 줄 바꿈입니다.
System.out.println 이 출력 문장의 핵심 로직: 객체를 출력할 때, 내부적으로 객체의 toString 메서드를 호출하여 객체를 문자열로 변환한 후 콘솔에 출력하고, 출력이 완료된 후 줄 바꿈 처리를 수행합니다.
3.equals 메서드:
사용자 정의 클래스에서 equals 메서드를 재정의하지 않으면 기본적으로 최상위 부모 클래스 Object의 equals 메서드를 사용하여 비교합니다. 최상위 부모 클래스 Object의 equals 메서드는 기본적으로 두 객체의 주소 값이 동일한지 비교합니다. 대부분 주소 값은 유용하지 않으며, 실제로는 객체의 속성 값을 비교하는 경우가 많습니다. 속성 값이나 다른 내용을 비교하려면 최상위 부모 클래스 Object의 equals 메서드를 재정의해야 합니다.
4. 코드 데모:
1.toString 메서드:
최상위 부모 클래스인 Object 클래스의 toString 메서드를 재정의하지 않았을 때:
package com.example.objectdemo;
public class Person {
//수동으로 다른 클래스를 상속하지 않았으므로 기본적으로 Object 클래스를 상속합니다
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.example.objectdemo;
public class ObjectDemo1 {
public static void main(String[] args) {
//1.toString 메서드: 객체의 문자열 표현을 반환
Object obj = new Object();
String str1 = obj.toString();
System.out.println(str1);
/*실행 결과: java.lang.Object@b4c966a
@ 이전: 패키지 이름과 클래스 이름
@ 자체: 고정된 형식
@ 이후: 객체의 주소 값 */
Person person = new Person();
String str2 = person.toString();
System.out.println(str2);
//실행 결과: com.example.objectdemo.Person@4e50df2e
//세부 사항: toString 메서드를 호출하지 않고 person 객체를 직접 출력
System.out.println(person);
//실행 결과: com.example.objectdemo.Person@4e50df2e, toString 메서드를 호출한 결과와 동일
/*System은 클래스, out은 System 클래스의 정적 변수
System.out은 출력 객체로 간단히 이해
println은 메서드, 매개변수는 출력할 내용을 나타냄*/
/*System.out.println 이 출력 문장의 핵심 로직: 객체를 출력할 때, 내부적으로 객체의 toString 메서드를 호출하여 객체를 문자열로 변환한 후 콘솔에 출력하고, 출력이 완료된 후 줄 바꿈 처리를 수행합니다*/
/*기본적으로 Object 클래스의 toString 메서드는 주소 값을 반환합니다.
따라서 기본적으로 사용자 정의 객체를 출력하면 실제로는 주소 값을 출력하는 것입니다.
하지만 주소 값은 대부분 유용하지 않으므로, 주소 값을 출력하지 않으려면 최상위 부모 클래스인 Object 클래스의 toString 메서드를 재정의하여 필요한 내용을 다시 입력할 수 있습니다*/
}
}
최상위 부모 클래스인 Object 클래스의 toString 메서드를 재정의했을 때:
package com.example.objectdemo;
public class Person {
//수동으로 다른 클래스를 상속하지 않았으므로 기본적으로 Object 클래스를 상속합니다
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return name + ", " + age;
}
}
package com.example.objectdemo;
public class ObjectDemo1 {
public static void main(String[] args) {
//1.toString 메서드: 객체의 문자열 표현을 반환
Object obj = new Object();
String str1 = obj.toString();
System.out.println(str1);
/*실행 결과: java.lang.Object@b4c966a
@ 이전: 패키지 이름과 클래스 이름
@ 자체: 고정된 형식
@ 이후: 객체의 주소 값 */
Person person = new Person("홍길동", 25);
String str2 = person.toString();
System.out.println(str2);
//실행 결과: 홍길동, 25
//세부 사항: toString 메서드를 호출하지 않고 person 객체를 직접 출력
System.out.println(person);
//실행 결과: 홍길동, 25, toString 메서드를 호출한 결과와 동일
/*System은 클래스, out은 System 클래스의 정적 변수
System.out은 출력 객체로 간단히 이해
println은 메서드, 매개변수는 출력할 내용을 나타냄*/
/*System.out.println 이 출력 문장의 핵심 로직: 객체를 출력할 때, 내부적으로 객체의 toString 메서드를 호출하여 객체를 문자열로 변환한 후 콘솔에 출력하고, 출력이 완료된 후 줄 바꿈 처리를 수행합니다*/
/*기본적으로 Object 클래스의 toString 메서드는 주소 값을 반환합니다.
따라서 기본적으로 사용자 정의 객체를 출력하면 실제로는 주소 값을 출력하는 것입니다.
하지만 주소 값은 대부분 유용하지 않으므로, 주소 값을 출력하지 않으려면 최상위 부모 클래스인 Object 클래스의 toString 메서드를 재정의하여 필요한 내용을 다시 입력할 수 있습니다*/
}
}
2.equals 메서드:
최상위 부모 클래스인 Object 클래스의 equals 메서드를 재정의하지 않았을 때:
package com.example.objectdemo;
public class Person {
//수동으로 다른 클래스를 상속하지 않았으므로 기본적으로 Object 클래스를 상속합니다
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return name + ", " + age;
}
}
package com.example.objectdemo;
public class ObjectDemo2 {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();
boolean result1 = p1.equals(p2);
System.out.println(result1);
/*실행 결과: false. equals 메서드는 p1이 호출하며, p1은 Person 타입입니다. 하지만 현재 Person 클래스에는
equals 메서드가 없으므로 부모 클래스 즉, 최상위 부모 클래스 Object의 equals 메서드를 찾게 됩니다. 최상위 부모 클래스 Object의 equals 메서드는
기본적으로 두 객체의 주소 값이 동일한지 비교합니다. p1과 p2는 모두 new로 생성되었으므로 주소 값이 다를 것이며, 따라서 equals 메서드는 false를 반환합니다.
대부분 주소 값은 유용하지 않으며, 실제로는 객체의 속성 값을 비교하는 경우가 많습니다. 속성 값이나 다른 내용을 비교하려면 최상위 부모 클래스 Object의 equals 메서드를 재정의해야 합니다*/
}
}
최상위 부모 클래스인 Object 클래스의 equals 메서드를 재정의했을 때:
package com.example.objectdemo;
import java.util.Objects;
public class Person {
//수동으로 다른 클래스를 상속하지 않았으므로 기본적으로 Object 클래스를 상속합니다
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return name + ", " + age;
}
//재정의된 equals 메서드는 객체 내부의 속성 값을 비교합니다
@Override
public boolean equals(Object o) {
//1. 먼저 호출자 this와 매개변수 객체가 동일한 객체인지 비교
if (this == o) return true; //이 if 문에서는 주소 값을 비교하며, 주소 값이 같으면 동일한 객체라고 판단
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
}
package com.example.objectdemo;
public class ObjectDemo2 {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();
boolean result1 = p1.equals(p2);
System.out.println(result1);
/*실행 결과: true, 속성 값이 모두 기본 생성자이므로 동일하므로 결과는 true*/
}
}
5. 연습:
package com.example.objectdemo;
public class ObjectDemo3 {
public static void main(String[] args) {
String s = "abc";
StringBuilder sb = new StringBuilder("abc");
System.out.println(s.equals(sb));
/*실행 결과: false, equals 메서드는 s가 호출하며, s는 String 타입이므로 equals 메서드는 String 클래스의 것을 확인해야 합니다.
문자열 String 클래스의 equals 메서드는 먼저 매개변수가 문자열인지 확인하고, 문자열이면 내부 속성을 비교하여
내부 속성이 일치하면 true를 반환하고, 다르면 false를 반환합니다. 매개변수가 문자열이 아니면 바로 false를 반환합니다*/
//sb는 문자열이 아니라 StringBuilder 객체입니다
System.out.println(sb.equals(s));
/*실행 결과: false, equals 메서드는 sb가 호출하며, sb는 StringBuilder 타입이므로 equals 메서드는 StringBuilder 클래스의 것을 확인해야 합니다.
StringBuilder 클래스는 equals 메서드를 재정의하지 않았으며, StringBuilder는 AbstractStringBuilder를 상속합니다.
AbstractStringBuilder 클래스도 equals 메서드를 재정의하지 않았으므로, StringBuilder 클래스는 기본적으로 최상위 부모 클래스 Object의 equals 메서드를 사용합니다.
최상위 부모 클래스 Object의 equals 메서드는 기본적으로 주소 값을 비교하며, s와 sb의 주소 값이 다르므로 false를 반환합니다*/
}
}
String 클래스의 equals 메서드: 먼저 호출자와 매개변수를 비교하여 같으면 true를 반환하고, 다르면 두 번째 return 문으로 이동합니다. 먼저 매개변수가 String 타입인지 확인하고, 그렇지 않으면 false를 반환합니다. String 타입이면 내부 속성을 계속 비교하여, 내부 속성이 일치하면 true를 반환하고, 다르면 false를 반환합니다.
StringBuilder 클래스는 equals 메서드를 재정의하지 않았으며, StringBuilder는 AbstractStringBuilder를 상속합니다. AbstractStringBuilder 클래스도 equals 메서드를 재정의하지 않았으므로, StringBuilder 클래스는 기본적으로 최상위 부모 클래스 Object의 equals 메서드를 사용합니다. 최상위 부모 클래스 Object의 equals 메서드는 기본적으로 주소 값을 비교합니다.