일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- Spring Boot
- JWT
- 도커
- 자료형
- Spring
- 자바
- Kotlin
- service
- axios
- 기초설정
- netty
- 프로젝트
- Java
- 채팅
- MySQL
- Security
- 네티 클라이언트
- toyproject
- springboot
- 클래스
- 네티 서버
- recoil
- 코틀린
- Repository
- 백엔드 설정
- 스프링부트
- 배열
- controller
- react
- 팀프로젝트
- Today
- Total
hyuko
Object 본문
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로 뜬다.
'Java > Java 고급편' 카테고리의 다른 글
컬렉션(Set, Map) (0) | 2023.04.24 |
---|---|
제네릭, 컬렉션 (0) | 2023.04.24 |
static 과 singletone pattern (0) | 2023.04.24 |
상속과 추상 그리고 인터페이스 (0) | 2023.04.24 |
배열, 클래스, 생성자, 메소드를 사용한 프로그램완성(2차원 배열) (0) | 2023.04.24 |