Object 클래스
Object 와 유사한 이름을 가진 java.lang.Objects 클래스는 객체 비교, 해시코드 생성, null 여부, 객체 문자열 리턴 등의 연산을 수행하는 정적 메소드들로 구선된 Object의 유틸리티 클래스이다. 다음은 Objects 클래스가 가지고 있는 정적 메소드들이다.
리턴 타입 | 메소드(매개 변수) | 설명 |
int | compare(T a, T b, Comparator<T> c) | 두 객체 a와 b를 Comparator를 사용해서 비교 |
boolean | deepEquals(Object a, Object b) | 두 객체의 깊은 비교(배열의 항목까지 비교) |
boolean | equals(Object a, Object b) | 두 객체의 얕은 비교(번지만 비교) |
int | hash(Object... values) | 매개값이 저장된 배열의 해시코드 생성 |
int | hashCode(Object o) | 객체의 해시코드 생성 |
boolean | isNull(Object obj) | 객체가 null인지 조사 |
boolean | nonNull(Object obj) | 객체가 null이 아닌지 조사 |
T | requireNonNull(T obj) | 객체가 null인 경우 예외 발생 |
T | requireNonNull(T obj, String message) | 객체가 null인 경우 예외 발생(주어진 예외 메시지 포함) |
T | requireNonNull(T obj, Supplier<String> messageSupplier) | 객체가 null인 경우 예외 발생(람다식이 만든 예외 메시지 포함) |
String | toString(Object o) | 객체의 toString() 리턴값 리턴 |
String | toString(Object o, String nullDefault) | 객체의 toString() 리턴값 리턴, 첫 번째 매개값이 null일 경우 두 번째 매개값 리턴 |
객체 비교(compare(T a, T b, Comparator<T> c))
Objects.compare(T a, T b, Comparator<T> c) 메소드는 두 객체를 비교자(Comparator)로 비교해서 int 값을 리턴한다. java.util.Comparator<T>는 제네릭 인터페이스 타입으로 두 객체를 비교하는 compare(T a, T b) 메소드가 정의되어 있다. 제네릭은 나중에 다룰건데, 여기서는 T가 비교할 객체 타입이라는 것만 알아두자. compare() 메소드의 리턴 타입은 int인데, a가 b보다 작으면 음수, 같으면 0, 크면 양수를 리턴하도록 구현 클래스를 만들어야 한다.
public interface Comparator<T> {
int compare(T a, T b);
}
다음 예제는 학생 객체에서 학생 번호로 비교하는 StudentComparator 구현 클래스를 작성한 것이다. a의 sno가 작으면 -1, 같으면 0, 크면 1을 리턴하도록 했다.
// StudentComparator.java -- 학생 번호 비교자
class StudentComparator implements Comparator<Student> {
@Override
public int compare(Student a, Student b) {
if(a.sno<b.sno) return -1;
else if(a.sno == b.sno) return 0;
else return 1;
}
}
// CompareExample.java -- 비교자 사용
public class CompareExample {
public static void main(String[] args) {
Student s1 = new Student(1);
Student s2 = new Student(1);
Student s3 = new Student(2);
int result = Objects.compare(s1, s2, new StudentComparator());
System.out.println(result);
result = Objects.compare(s1, s3, new StudentComparator());
System.out.println(result);
}
static class Student {
int sno;
Student(int sno) {
this.sno = sno;
}
}
static class StudentComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
/*
if(o1.sno<o2.sno) return -1;
else if(o1.sno == o2.sno) return 0;
else return 1
*/
return Integer.compare(o1.sno, o2.sno);
}
}
}
동등 비교(equalse()와 deepEquals())
Objects.equals(Object a, Object b)는 두 객체의 동등을 비교하는데 다음과 같은 결과를 리턴한다. 특이한 점은 a와 b가 모두 null일 경우 true를 리턴한다는 점이다. a와 b가 null이 아닌 경우는 a.equals(b)의 결과를 리턴한다.
a | b | Objects.equals(a, b) |
not null | not null | a.equals(b)의 리턴값 |
null | not null | false |
not null | null | false |
null | null | true |
Objects.deepEquals(Object a, Object b) 역시 두 객체의 동등을 비교하는데, a와 b가 서로 다른 배열일 경우, 항목 값이 모두 값다면 true를 리턴한다. 이것은 Arrays.deepEquals(Object[] a, Object[] b)와 동일하다.
a | b | Objects.deepEquals(a, b) |
not null(not array) | not null(not array) | a.equals(b)의 리턴값 |
not null(array) | not null(array) | Arrays.deepEquals(a, b)의 리턴값 |
not null | null | false |
null | not null | false |
null | null | true |
해시코드 생성(hash(), hashCode())
Objects.hash(Object... values) 메소드는 매개값으로 주어진 값들을 이용해서 해시 코드를 생성하는 역할을 하는데, 주어진 매개값들로 배열을 생성하고 Arrays.hashCode(Object[])를 호출해서 해시코드를 얻고 이 값을 리턴한다. 이 메소드는 클래스가 hachCode()를 오버라이딩할 때 리턴값을 생성하기 위해 사용하면 좋다. 클래스가 여러 가지 필드를 가지고 있을 때 이 필드들로부터 해시코드를 생성하게 되면 동일한 필드값을 가지는 객체는 동일한 해시코드를 가질 수 있다.
@Override
public int hashCode() {
return Objects.hash(field1, field2, field3);
}
Objects.hashCode(Object o)는 매개값으로 주어진 객체의 해시코드를 리턴하기 때문에 o.hashCode()의 리턴값과 동일하다. 차이점은 매개값이 null이면 0을 리턴한다. 다음 예제는 Student 객체의 해시코드를 생성하기 위해 Student의 필드인 sno와 name을 매개값으로 해서 Objects.hash() 메소드를 호출했다. 학생 번호와 이름이 동일하다면 같은 해시코드를 얻을 수 있다는 것을 보여준다.
// HashCodeExample.java
public class HashCodeExample {
public static void main(String[] args) {
Student s1 = new Student(1, "홍길동");
Student s2 = new Student(1, "홍길동");
System.out.println(s1.hashCode());
System.out.println(Objects.hashCode(s2));
}
static class Student {
int sno;
String name;
Student(int sno, String name) {
this.sno = sno;
this.name = name;
}
@Override
public int hashCode() {
return Objects.hash(sno, name);
}
}
}
널 여부 조사(isNull(), nonNull(), requireNonNull())
Objects.isNull(Object obj)는 매개값이 null일 경우 true를 리턴한다. 반대로 nonNull(Object obj)는 매개값이 not null일 경우 true를 리턴한다. requireNonNull()는 다음 세 가지로 오버로딩되어 있다.
리턴 타입 | 메소드(매개 변수) | 설명 |
T | requireNonNull(T obj) | not null -> obj null -> NullPointerException |
T | requireNonNull(T obj, String message) | not null -> obj null -> NullPointerException(message) |
T | requireNonNull(T obj, Supplier<String> msgSupplier) | not null -> obj null -> NullPointerException(msgSupplier.get()) |
첫 번째 매개값이 not null이면 첫 번째 매개값을 리턴하고, null이면 모두 NullPointerException을 발생시킨다. 두 번째 매개값은 NullPointerException의 예외 메시지를 제공한다.
// NullExample.java -- null 여부 조사
public class NullExample {
public static void main(String[] args) {
String str1 = "홍길동";
String str2 = null;
System.out.println(Objects.requireNonNull(str1));
try {
String name = Objects.requireNonNull(Str2);
}
catch(Exception e) {
System.out.println(e.getMessage());
}
try {
String name = Objects.requireNonNull(str2, "이름이 없습니다.");
}
catch(Exception e) {
System.out.println(e.getMessage());
}
try {
String name = Objects.requireNonNull(str2, ()->"이름이 없다니까요?"); // 람다식
}
catch(Exception e) {
System.out.println(e.getMessage());
}
}
}
21라인을 보면 두 번째 매개값으로 람다식을 주었다. 람다식은 나중에 다룰것이다. 람다식은 인터페이스의 구현 객체이므로 Supplier 구현 객체로 람다식을 대입했다.
객체 문자 정보(toString())
Objects.toString()은 객체의 문자 정보를 리턴하는데, 다음 두 가지로 오버로딩되어 있다.
리턴 타입 | 메소드(매개 변수) | 설명 |
String | toString(Object o) | not null -> o.toString() null -> "null" |
String | toString(Object o, String nullDefault) | not null -> o.toString() null -> nullDefault |
첫 번째 매개값이 not null이면 toString()으로 얻을 값을 리턴하고, null이면 "null" 또는 두 번째 매개값인 nullDefault를 리턴한다.
// ToStringExample.java -- 객체 문자 정보
public class ToStringExample {
public static void main(String[] args) {
String str1 = "홍길동";
String str2 = null;
System.out.println(Objects.toString(str1));
System.out.println(Objects.toString(str2));
System.out.println(Objects.toString(str2, "이름이 없습니다."));
}
}
'Java 길찾기 > 이것이 자바다' 카테고리의 다른 글
[Java] 기본 API 클래스 - Class (0) | 2022.02.23 |
---|---|
[Java] 기본 API 클래스 - System (0) | 2022.02.22 |
[Java] 기본 API 클래스 - Object (0) | 2022.02.18 |
[Java] 사용자 정의 예외, 예외 정보 얻기 (0) | 2022.02.17 |
[Java] 예외 떠넘기기 (0) | 2022.02.16 |