TIL. Object 클래스

hyuko·2023년 1월 11일
0

Java

목록 보기
21/26

Object 클래스

오브젝트 클래스란?

  • 모든 클래스의 최상위 객체이다.
  • 기본적으로 모든 클래스들은 Object클래스를 상속을 받고 있다.
  • 그렇기 때문에 생략이 가능하다.

이 생략이 되있던 것은 생성자를 만들었을 때 알 수 있다.

// 예를 들어 하나의 상속을 받지 않은 Student 클래스의
// 생성자를 만든다고 해보자

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

위의 코드처럼 super(); 가 나온다.
우리가 상속을 배웠을 때 super라는 것은 부모 객체를 의미하는데

우리가 처음 Student라는 클래스를 만들 당시에 상속을 받은 적이 없다.
하지만 super가 들어가 있는 것을 볼 수 있다.

이 것이 바로 기본적으로 클래스는 Object클래스를 상속을 받는다.

그렇다면 최상위 객체인 Object의 메소드들을 상속을 받은 상태이니
마음대로 오버라이드 해서 재정의가 가능하다.

그렇다면 그 메소드들에 대해 배워보도록 한다.


오브젝트의 메소드

toString() 메소드

  • 기본적으로 모든 Object 클래스는 생성할 당시에 toString을
    들고 있다. 그래서 출력하게 되면 Object객체와 따로 toString을
    String 값에 넣어 출력 한것과 동일한 결과가 나온다.
 	Object obj = new Object();
 	System.out.println(obj);
    
	String str = obj.toString();
 	
    // 하지만 obj객체가 String은 아니기에 대입이 불가하다
    //String str2 = obj;
 	
    System.out.println(str);
    
    Student student1 = new Student("홍길동", 29);
	Student student2 = new Student("이순신", 35);
    Student student3 = new Student("김유신", 23);
    Student student4 = new Student("강감찬", 15);

	System.out.println(student1);
    System.out.println(student2);
    System.out.println(student3);
    System.out.println(student4);

	System.out.println();

	System.out.println(student1.toString());
    System.out.println(student2.toString());
    System.out.println(student3.toString());
    System.out.println(student4.toString());
    
  • 위의 코드를 콘솔화면에 출력해보자

toString은 메소드이고 우리는 Object를 항상 상속받는 클래스의 경우 toString을 오버라이드하여 재정의해서 toString을 바꿔서 쓸 수 있다.


Equals

  • equals 란 : 영어 뜻 대로 같다 라는 의미 이다.

우리가 이전에 배웠던 비교는 비교연사자인 == 비교를 하게 되는데,
이 == 연산자는 주소값 비교이기 때문에, 예를 들어 String부분에서 오류가 있다.

코드로 한번 살펴 보도록하자.

// 이러한 변수가 있다고 해보자

String name1 = "김유신";
String name2 = "김유신";

System.out.println(name1 == name2);

// 위의 코드를 실행하게되면 true값이 나온다.

위의 코드를 보고 의아할 수 있다.
왜냐하면 같은 값이 각각의 변수에 대입이 되어있으니 같은게 당연한게 아닌가 하고 말이다.

본래의 String은 클래스이다.
그렇기 때문에 본래에는 new String(""); 으로 생성을 해주어야 하지만
이미 리터럴 상수 값으로 문자열이 정의되어 있기 때문에 생략이 되어져 있는 것이다.

그렇다면 class객체를 이용해서 위와 비슷한 예제를 가지고 왜 == 비교를
하면 안되는지를 알아보자.

Student s1 = new Student("김유신", 45);
Student s2 = new Student("김유신", 45);

System.out.println(s1 == s2);

위의 코드는 false가 뜬다 . 왜냐하면 String을 생각하면 true가 떠야하지 않나 싶지만 위의 생성은 각각 다른 생성이고 그렇게되면 메모리에 할당이 될 때 각각 다른 주소를 생성하게 된다. 그렇기 때문에 == 비교를 했을 때
주소 값이 다르기 때문에 false가 뜨게된다.

이렇게 객체의 매개변수의 값이나 같은 클래스로 생성이 각각 되었지만,
값을 비교해서 같을 때와 같지 않을 때의 조건을 사용하고 싶을 때
equals를 쓰게된다.

@Override
public boolean equals(Object obj) {
	if (this == obj){
    // 매개변수로 들어오는 객체가 현재 클래스와 같은지 비교
    	return true;
    }
    if (obj == null) {
    // 매개변수로 들어오는 객체가 null인지 체크
    	return false;
    }
    if(!(obj.getClass() == Student.class)){
    // 매개변수의 getClass가 Student클래스 인지 체크
        return false;
    }

// Student 라는 s변수에 매개변수를 Student 클래스로 다운캐스팅한다.
	Student s = (Student) obj;
    // 반환을 하는데 클래스 자신의 이름과 변환된 s의 이름이 같으면서
    // 나이도 같을 경우 true가 반환 아닐경우 false가 반환
    return name.equals(s.name) && age == s.age;
}

위의 코드는 Object의 메소드인 equals를 오버라이드해서 재정의 한다.
각각의 조건을 거치고 나서 비교를 하는 로직이다.


String name1 = "김유신";
String name2 = "홍길동";
String name3 = new String("김유신");

// true 반환
System.out.println(name1.equals(name3));

Student s1 = new Student("김유신", 45);
Student s2 = new Student("김유신", 45);
SubStudent s3 = new SubStudent("김유신", 45);

// false 반환 : 이유는 s3는 Student 클래스가 아니다.
// Student 클래스로 casting을 할 수가 없다.
System.out.println(s1.equals(s3));

getClass()

  • getClass : 이 메소드에는 모든 클래스가 생성이 될 때 그 클래스에 대한
    정보들이 담긴다.

그러므로 getClass를 이용해서 정보를 찾아낼 수 있다.


public static void main(String[] args) {
        Student student = new Student("홍길동", 37);



        System.out.println(student.getClass());
        System.out.println(Student.class);

        // 다른패키지에도 같은 이름의 클래스가 있을수 있다. 그래서 패키지까지 표현한다.
        System.out.println(student.getClass().getName());

        Class<?> studentClass = student.getClass();

        // 클래스 이름만.
        System.out.println(studentClass.getSimpleName());

        // getDeclared 가 붙으면 지정자가 무엇이든 들고오고 그냥 get 뒤에 오는 것은 public 이어야만 들고 올수 있다.
        Field[] fields = studentClass.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        System.out.println();

        Method[] methods = studentClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }

생성이 된 Student의 student 변수의 getClass의 값과 Student.class
를 비교해서 같은지 보았다.


hashcode()

  • hashcode : 10진수 값으로 변환한 주소 값.

우리가 비교를 할 때 equals 와 == 를 배웠다.
이 방법으로 비교를 하는 경우는 클래스의 다름의 유무와는 상관이 없고
그 객체가 담고 있는 값이 같으면 같다라는 개념을 쓸 때에 사용을 한다.
그냥 값만을 비교하고 싶을 때 쓰는방법이다.

@Override
public int hashCode() {        
    return Objects.hash(name, age);
}

// 여기서 hash는 Objects의 메소드로 
//10진수 값으로 더해서 나타내준다.

===================================

public static void main(String[] args) {
	Student s1 = new Student("홍길동", 30);
    Student s2 = new Student("홍길동", 30);
    SubStudent s3 = new SubStudent("홍길동", 30);

    System.out.println(s1.hashCode());
    System.out.println(s2.hashCode());

    System.out.println(s1.hashCode() == s3.hashCode());
}

// 위의 비교는 true가 뜬다.

앞에서 봤던 equals였다면 false가 나왔을 것이다.
SubStudent는 Student클래스로 형변환이 될 수 없기 때문에
하지만 두 객체의 매개변수안의 값들이 같은지 비교를 하기 위해
hashcode를 쓰면 값이 같기에 true로 뜬다.


profile
백엔드 개발자 준비중

0개의 댓글