Help us understand the problem. What is going on with this article?

クラス java.util.Objectsのおさらいメモ

概要

Java 1.7より導入されたjava.util.Objectsクラスのおさらいメモです。

環境

  • Windows 10 Professional
  • Oracle JDK 1.8.0_144
  • Oracle JDK 9.0.4
  • Oracle JDK 10.0.1

参考

Employeeクラス

この記事のサンプルコードでは下記のEmployeeクラスを使います。

Employee
public class Employee {
  private Long id;
  private String name;

  public Employee(Long id, String name) {
    this.id = id;
    this.name = name;
  }

  @Override
  public String toString() {
    return "Employee{" +
        "id=" + id +
        ", name='" + name + '\'' +
        '}';
  }

  // getter/setterは省略
}

Objects

compare

Employee emp1 = new Employee(100L, "rubytomato");
Employee emp2 = new Employee(200L, "garnetpepper");

System.out.println(Objects.compare(emp1, emp2, Comparator.comparing(Employee::getId)));
// → -1
System.out.println(Objects.compare(emp1, emp1, Comparator.comparing(Employee::getId)));
// → 0
System.out.println(Objects.compare(emp2, emp1, Comparator.comparing(Employee::getId)));
// → 1

第1引数の比較対象がnullの場合、NullPointerExceptionが発生しますが、nullを許容したい場合はComparator#nullsFirst(nullを最小値とする)またはComparator#nullsLast(nullを最大値とする)を指定します。

Employee emp1 = new Employee(null, "rubytomato");
Employee emp2 = new Employee(200L, "garnetpepper");

System.out.println(Objects.compare(emp1, emp2,
        Comparator.comparing(Employee::getId, Comparator.nullsLast(Comparator.naturalOrder()))));
// → 1

LocalDateTimeでの例です。

LocalDateTime d1 = LocalDateTime.of(2017, 8, 1, 0, 0, 0);
LocalDateTime d2 = LocalDateTime.of(2017, 8, 2, 0, 0, 0);

System.out.println(Objects.compare(d1, d2, LocalDateTime::compareTo));
// → -1
System.out.println(Objects.compare(d1, d1, LocalDateTime::compareTo));
// → 0
System.out.println(Objects.compare(d2, d1, LocalDateTime::compareTo));
// → 1

Integerでの例です。

Integer i1 = 100;
Integer i2 = 200;

System.out.println(Objects.compare(i1, i2, Integer::compareTo));
// → -1
System.out.println(Objects.compare(i1, i1, Integer::compareTo));
// → 0
System.out.println(Objects.compare(i2, i1, Integer::compareTo));
// → 1

// 自然順序付け
System.out.println(Objects.compare(i1, i2, Comparator.naturalOrder()));
// → -1
System.out.println(Objects.compare(i1, i1, Comparator.naturalOrder()));
// → 0
System.out.println(Objects.compare(i2, i1, Comparator.naturalOrder()));
// → 1

equals

Objects#equalsは第1引数のオブジェクトのequalsメソッドを使ってオブジェクト同士が等しいか判定を行います。どちらかのオブジェクトがnullの場合はfalseを返します。
第1引数のオブジェクトがnullの場合でもNullPointerExceptionは発生しません。
ただし、判定する両方のオブジェクトがnullの場合はtrueが返ります。

テストデータ
Employee emp1 = new Employee(100L, "rubytomato");
Employee emp1Null = null;
Employee emp2 = new Employee(200L, "garnetpepper");
Employee emp2Null = null;

Objects#equals

Objects#equalsを使った例です。nullの場合でもNullPointerExceptionはスローされません。

Objects
System.out.println(Objects.equals(emp1, emp2));
// → false

System.out.println(Objects.equals(emp1, emp2Null));
// → false

System.out.println(Objects.equals(emp1Null, emp2));
// NullPointerExceptionはスローされない
// → false

System.out.println(Objects.equals(emp1, emp1));
// → true

System.out.println(Objects.equals(emp1Null, emp2Null));
// null同士はtrueが返る
// → true

Object.equals

Object
System.out.println(emp1.equals(emp2));
// → false

System.out.println(emp1.equals(emp2Null));
// → false

System.out.println(emp1Null.equals(emp2));
// → NullPointerExceptionがスローされる

System.out.println(emp1.equals(emp1));
// → true

System.out.println(emp1Null.equals(emp2Null));
// → NullPointerExceptionがスローされる

deepEquals

使いどころがよくわかっていないのですが、配列同士を比較する際に使用するようです。
なお配列同士の比較を行うと内部的にArrays.deepEqualsへ処理を委譲しています。

テストデータ
Employee emp1 = new Employee(100L, "rubytomato");
Employee emp2 = new Employee(200L, "garnetpepper");
Employee emp3 = new Employee(300L, "rubytomato");

Employee[] emps1 = new Employee[]{emp1, emp2, emp3};
Employee[] emps2 = new Employee[]{emp1, emp2, emp3};

Objects#deepEquals

Objects
System.out.println(Objects.deepEquals(emps1, emps2));
// → true

emps1 = null;

System.out.println(Objects.deepEquals(emps1, emps2));
// NullPointerExceptionはスローされません
// → false

Object.equals

Object
System.out.println(emps1.equals(emps2));
// → false

emps1 = null;

System.out.println(emps1.equals(emps2));
// → NullPointerExceptionがスローされる

ちなみにコレクション同士だと両方ともtrueが返ります。

Employee emp1 = new Employee(100L, "rubytomato");
Employee emp2 = new Employee(200L, "garnetpepper");
Employee emp3 = new Employee(300L, "rubytomato");

List<Employee> emps1 = Arrays.asList(emp1, emp2, emp3);
List<Employee> emps2 = Arrays.asList(emp1, emp2, emp3);
System.out.println(Objects.deepEquals(emps1, emps2));
// → true

System.out.println(emps1.equals(emps2));
// → true

isNull

導入されたバージョン: 1.8

JavaDoc
APIの注:
このメソッドは、Predicate(filter(Objects::isNull))として使用するために存在します。

配列にnullが含まれているかチェックする例です

テストデータ
String[] params = {"p1", "p2", null, "p4", null, "p6"};
System.out.println(Arrays.stream(params).anyMatch(Objects::isNull));
// → true

System.out.println(Arrays.stream(params).filter(Objects::isNull).count());
// → 2

nonNull

導入されたバージョン: 1.8

JavaDoc
APIの注:
このメソッドは、Predicate(filter(Objects::nonNull))として使用するために存在します。

配列からnullの要素を除外する例です

テストデータ
String[] params = {"p1", "p2", null, "p4", null, "p6"};
Arrays.stream(params).filter(Objects::nonNull).forEach(System.out::println);
// → p1
// → p2
// → p4
// → p6

requireNonNull

導入されたバージョン: 1.8

引数に取るオブジェクトのnullチェックを行います。
引数がnullでなければ引数をそのまま返し、nullであればNullPointerExceptionをスローします。

Employee emp = null;

Objects.requireNonNull(emp);
// → java.lang.NullPointerException

第2引数にNullPointerExceptionをスローするときのエラーメッセージを指定することができます。

Employee emp = null;

Objects.requireNonNull(emp , "employee must not be null");
// メッセージ付きで例外がスローされる
// → java.lang.NullPointerException: employee is null

NullPointerExceptionをスローする前に何か実行する必要がある場合は、第2引数にラムダ式を指定します。

Employee emp = null;

Objects.requireNonNull(emp, () -> {

  // do something else.

  return "employee must not be null";
});
// メッセージ付きで例外がスローされる
// → java.lang.NullPointerException: employee is null 

toString

Objects#toStringを使用するとオブジェクトがnullかどうかを気にしなくてもよくなります。

Objects#toString

empがnullのときは"null"という文字列を返します。

Objects
Employee emp = new Employee(100L, "rubytomato");

System.out.println(Objects.toString(emp));
// → Employee{id=100, name='rubytomato'}

emp = null;

System.out.println(Objects.toString(emp));
// "null"という文字列が返ります
// → null

第2引数にnullの場合の代替文字列を指定することができます。

System.out.println(Objects.toString(emp, "employee is null"));
// → employee is null

Object.toString

Object
Employee emp = new Employee(100L, "rubytomato");

System.out.println(emp.toString());
// → Employee{id=100, name='rubytomato'}

emp = null;

System.out.println(emp.toString());
// → java.lang.NullPointerExceptionをスロー

Java 9で追加されたAPI

requireNonNullElse

Java 1.8で追加されたrequireNonNullにバリエーションが増えました。

public void demo(String obj1, String obj2) {
    String result = Objects.requireNonNullElse(obj1, obj2);
    System.out.println("result : " + result);
}
demo("obj1", "obj2");
// result : obj1

demo("obj1", null);
// result : obj1

demo(null, "obj2");
// result : obj2

// demo(null, null);
// java.lang.NullPointerException: defaultObj

requireNonNullElseGet

public void demo2(String obj, Supplier<String> supplier) {
    String result = Objects.requireNonNullElseGet(obj, supplier);
    System.out.println("result : " + result);
}
demo("obj1", () -> "obj2");
// result : obj1

demo(null, () -> "obj2");
// result : obj2

//demo(null, () -> null);
// java.lang.NullPointerException: supplier.get()

checkIndex

indexが、0(inclusive)からlength(exclusive)の範囲内かチェックします。

public void demo(int index, String[] fruits) {
    int result = Objects.checkIndex(index, fruits.length);
    System.out.println("result : " + result + " fruits : " + fruits[index]);
}
String[] fruits = {"apple", "banana", "cherry"};

demo(0, fruits);
// result : 0 fruits : apple

demo(1, fruits);
// result : 1 fruits : banana

demo(2, fruits);
// result : 2 fruits : cherry

demo(3, fruits);
// java.lang.IndexOutOfBoundsException: Index 3 out-of-bounds for length 3

checkFromToIndex

from(inclusive)からto(exclusive)のサブレンジが、0(inclusive)からlength(exclusive)の範囲内かチェックします。

public void demo(int from, int to, String[] fruits) {
    int result = Objects.checkFromToIndex(from, to, fruits.length);
    System.out.println("result : " + result + " fruits : " + fruits[from]);
}
String[] fruits = {"apple", "banana", "cherry"};

demo(0, 1, fruits);
// result : 0 fruits : apple

demo(1, 2, fruits);
// result : 1 fruits : banana

demo(2, 3, fruits);
// result : 2 fruits : cherry

demo(2, 4, fruits);
// java.lang.IndexOutOfBoundsException: Range [2, 4) out-of-bounds for length 3

checkFromIndexSize

from(inclusive)からfrom + size(exclusive)のサブレンジが、0(inclusive)からlength(exclusive)の範囲内かチェックします。

public void demo(int index, int size, String[] fruits) {
    int result = Objects.checkFromIndexSize(index, size, fruits.length);
    System.out.println("result : " + result + " fruits : " + fruits[index]);
}
String[] fruits = {"apple", "banana", "cherry"};

demo(0, 1, fruits);
// result : 0 fruits : apple

demo(1, 2, fruits);
// result : 1 fruits : banana

demo(2, 3, fruits);
// java.lang.IndexOutOfBoundsException: Range [2, 2 + 3) out-of-bounds for length 3

Preconditions

これらのstaticメソッドは、Preconditionsクラスへ処理を委譲しています。

Utility methods to check if state or arguments are correct.

Java 10で追加されたAPI

追加されたAPIはありません。

Java 11で追加されたAPI

追加されたAPIはありません。

Java 12で追加されたAPI

追加されたAPIはありません。

Java 13で追加されたAPI

追加されたAPIはありません。

Java 14で追加されたAPI

追加されたAPIはありません。

その他のおさらいメモ

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした