w1-2-Object(객체) 탐구하기
w1-Java_for_framework
📌 과제 설명
1. Object(객체) 탐구하기
- toString(), equals(), hashCode() 에 대해서 알아봅시다.
❔ 넌 어디서 왔니?
public class StringClassExam{ public static void main(String[] args) { System.out.println("System.out.println은 어디서 왔길래 사용할수 있을까?"); } }
java를 쓰면서, 콘솔출력을 많이 사용하게 되는데 출력에 대한 기능을 만들지도 않았는데,
위 코드를 치면 손쉽게 콘솔출력을 할 수 있게 됩니다. 그럼 System.out.println은 어디서 왔을까요?
해당 코드 위에 Ctrl + 마우스를 올려보면, Java의 lang 패키지를 보게 됩니다.
자세히 살펴보면extends Object
로 코드상에는 보이지 않는데, 자동적으로 Object를 상속 받고 있는 모습을 볼 수 있습니다.
Object클래스는 java.lang 패키지의 최상위 클래스입니다.
이 덕분에 java.lang에 들어있는 기능들을 불러 사용 할 수 있습니다. 그러므로 System.out은 java.lang 패키지 안에 포함되어 있어 사용이 가능 했던 겁니다. 추가로 생성한 클래스는 Object 클래스의 메소드를 사용할 수 있고(상속받았기에), 기존의 Object가 가진 메소드를 오버라이딩(재정의)도 할 수 있습니다.
이 중 Object 클래스 메소드 중toString()
,equals()
,hashCode()
에 대해서 알아봅시다!
👩💻 요구 사항과 구현 내용
❔ toString()에 대하여 알아보자!
1️⃣ 객체가 가지고 있는 정보나 값들을 문자열로 만들어 리턴하는 메소드
- Object를 상속받았기 때문에, toString()을 override을 하지 않으면 '(패키지명)클래스풀네임@해시코드'가 출력됩니다.
Object.java 에 정의되어 있는 toString
class Book {
String title;
String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
}
public class ObjectTest {
public static void main(String[] args) {
Book book = new Book("마시멜로 이야기", "엘런싱어 와 호아킴데포사다");
System.out.println(book); // 📣 Book@7a81197d
}
}
2️⃣ * override 작성 후 실행
public class ObjectTest {
public static void main(String[] args) {
Book book = new Book("마시멜로 이야기", "엘런싱어 와 호아킴데포사다");
System.out.println(book); // 📣 Book{title='마시멜로 이야기', author='엘런싱어 와 호아킴데포사다'}
}
}
class Book {
String title;
String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
@Override
public String toString() {
return "Book{" +
"title='" + title + '\'' +
", author='" + author + '\'' +
'}';
}
}
3️⃣ String 객체는 toString()을 안해도 문자열이 바로 반환됩니다.
String 클래스는 이미 toString()을 override 하고 있기 때문입니다.
String str = new String("Apple");
System.out.println(str); // 📣 Apple 📣 toString()을 안했는데 문자열이 출력됩니다.
❔ boolean equals(Object obj)에 대하여 알아보자!
equals는 내용이 같은지를 검사하는 메소드입니다.
다만 ==
연산자와 다른 점은 완전히 같은 객체를 가르키지 않아도 개발자가 true로 만들 수 있습니다.
즉 주소는 달라도, 내용이 같으면 같다고 봐서 true를 반환 할 수 있게 만듭니다.
==
는 주소의 값을 비교합니다.(Call By Reference)
equal()
는 reference type끼리는 주소를 비교합니다.(Call By Reference),
primitive type과 String Class, wrapper Class(Integer, Double 등)은 내용(Value)을 비교하도록 오버라이딩 되어있습니다.
public class equal {
public static void main(String[] args) {
// 비교연산 ==
String str1 = "abc";
String str2 = str1;
if (str1 == str2)
System.out.println("str1과 str2는 동일한 주소를 가지고 있습니다."); // 📣 true로 출력됨
else
System.out.println("서로 다른 주소를 가지고 있습니다.");
System.out.println(str1.equals(str2)); // 📣 true
// 객체에서의 equal()와 hashcode()
Test object1 = new Test("Na");
Test object2 = new Test("Na");
System.out.println(object1.equals(object2)); // 📣 false
// String에서의 equal()와 hashcode()
String string1 = new String("Na");
String string2 = new String("Na");
System.out.println(string1.equals(string2)); // 📣 true
}
}
class Test {
String name;
Test(String name) {
this.name = name;
}
}
string1
과string2
는 서로 다른 주소를 가지고 있지만,
String클래스는 이미 equals메서드가 오버라이드(재정의) 되어있어, 주소가 아닌 객체에 저장된 값을 비교하기 때문에 true가 나왔습니다. 다만 Test객체에서는name
만 같으면 같게 볼지, 모르기 때문에 false가 나왔습니다. 하지만==
랑 다른점은 완전히 같은 객체를 가르키지 않아도 개발자가 true로 만들 수 있다고 했었습니다. 그럼 equals()을 재정의 해보겠습니다.
public class equal {
public static void main(String[] args) {
// 객체에서의 equal()와 hashcode()
Test object1 = new Test("Na");
Test object2 = new Test("Na");
System.out.println(object1.equals(object2)); // 📣 true
// String에서의 equal()와 hashcode()
String string1 = new String("Na");
String string2 = new String("Na");
System.out.println(string1.equals(string2)); // 📣 true
}
}
class Test {
String name;
Test(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
Test anotherObj = (Test) obj;
return (this.name.equals(anotherObj.name));
}
}
위 코드처럼 equals()을 @Override 해주면 내용을 같은지 비교하여 true를 반환합니다.
❔ hashCode()에 대하여 알아보자!
- equals(Object) 메서드에 따라 두 객체가 같은 경우 두 객체 각각에 대해 hashCode 메서드를 호출하면 동일한 정수 결과가 생성되어야 합니다
- hashCode()가 같으면 equals()는 true다 라는 역은 성립하지 않습니다.
import java.util.Objects;
public class equal {
public static void main(String[] args) {
// 객체에서의 equal()와 hashcode()
Test object1 = new Test("Na");
Test object2 = new Test("Na");
System.out.println(object1.equals(object2)); // 📣 true
System.out.println(object1.hashCode()); // 📣 2546
System.out.println(object2.hashCode()); //📣 2546
// String에서의 equal()와 hashcode()
String string1 = new String("Na");
String string2 = new String("Na");
System.out.println(string1.equals(string2)); // 📣 true
System.out.println(string1.hashCode()); // 📣 2515
System.out.println(string2.hashCode()); // 📣 2515
}
}
class Test {
String name;
Test(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) { // equals() 메소드 재정의
Test anotherObj = (Test) obj;
return (this.name.equals(anotherObj.name));
}
@Override
public int hashCode() { // equals() 메소드를 재정의 하게되면 hashCode()메소드도 재정의를 해줘야 합니다.
return Objects.hash(name);
}
}
즉 equals(Object)가 서로 같은 객체(true)라면, hashcode()도 동일해야 합니다.
그 이유는 hash를 사용하는 Collection(HashSet, HashMap, ...)등에서 hash가 다르면 같은 값이라도 서로 다르게 인식하기 때문에, 반드시 equals()와 hashcode()는 함께 재정의 해야 합니다.
🔰 알쓸신잡 - String Hashcode 계산하는 방법
- s[i]는 문자열의 개별 문자를 나타냅니다.
- ^ 거듭제곱을 의미합니다.
- n 은 문자열의 길이를 나타냅니다.
- String에서 hashcode()의 반환값이 어떻게 나오는지에 대한 설명입니다.
hashcode는 int형으로 반환하는데, int는 4바이트는 31비트로 표현합니다. 31을 쓰는 이유는 홀수이고, 비트연산으로도 대체 가능하기 때문입니다. (비트연산은 곱셈보다 더 빠르게 처리할수있습니다.)(31 * i) == (i << 5) - i
는 동일합니다.(i << 5) - i
비트연산은2^32 -i
의미입니다.
import java.io.*;
class GFG {
public static void main(String[] args)
{
String str = "GFG";
System.out.println(str);
int hashCode = str.hashCode(); //GFG
System.out.println(hashCode); // 70472
}
}
🛑 문자열 3개일 시
s[] = {'G', 'F', 'G'}
n = 3
⭕ 문자열 해시코드값 구하기
s[0] x 31^(2)
+s[1] x 31^1
+s[2]
=G x 31^2
+F x 31
+G
= (G의 ASCII 값 = 71 그리고 F = 70)
71 x 31^2
+70 x 31
+71
=68231
+2170
+71
=70472
🛑 빈 문자열의 해시코드값 구하기
s[] = {}
n = 0
⭕ 해시코드 계산
s[0]*31^(0)
= 0
✅ PR 포인트 & 궁금한 점
제가 이해한 게 맞는지 궁금합니다!
Reference
Object (Java Platform SE 7 ) (oracle.com)
[Java]자바 기본 클래스 - Object 클래스 (velog.io)
자바 equals(), hashCode(), == 연산자 비교 및 개념 정리하기(객체 비교 구문 커스터마이징하는 방법) (tistory.com)
Author And Source
이 문제에 관하여(w1-2-Object(객체) 탐구하기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@p1atina/w1-2-Object객체-탐구하기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)