クラス 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

**参考**

* [Oracle JDK 9ドキュメント] (https://docs.oracle.com/javase/jp/9/index.html)
* [Oracle JDK 10ドキュメント] (https://docs.oracle.com/javase/jp/10/index.html)
* [Objects (java SE 10 & JDK 10)] (https://docs.oracle.com/javase/jp/10/docs/api/java/util/Objects.html)
* [Apache Commons Lang ObjectUtils] (https://commons.apache.org/proper/commons-lang/javadocs/api-release/index.html)

**Employeeクラス**

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

```java: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] (https://docs.oracle.com/javase/jp/8/docs/api/java/util/Objects.html)

## compare

```java
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を最大値とする)を指定します。

```java
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での例です。

```java
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での例です。

```java
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が返ります。

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

**Objects#equals**

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

```java: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**

```java: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`へ処理を委譲しています。

```java:テストデータ
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**

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

emps1 = null;

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

**Object.equals**

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

emps1 = null;

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

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

```java
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);
```

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

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


## isNull

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

> [JavaDoc] (https://docs.oracle.com/javase/jp/8/docs/api/java/util/Objects.html#isNull-java.lang.Object-)
> APIの注:
> このメソッドは、Predicate(filter(Objects::isNull))として使用するために存在します。

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

```java:テストデータ
String[] params = {"p1", "p2", null, "p4", null, "p6"};
```

```java
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] (https://docs.oracle.com/javase/jp/8/docs/api/java/util/Objects.html#nonNull-java.lang.Object-)
> APIの注:
> このメソッドは、Predicate(filter(Objects::nonNull))として使用するために存在します。

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

```java:テストデータ
String[] params = {"p1", "p2", null, "p4", null, "p6"};
```

```java
Arrays.stream(params).filter(Objects::nonNull).forEach(System.out::println);
// → p1
// → p2
// → p4
// → p6
```


## requireNonNull

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

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

```java
Employee emp = null;

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

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

```java
Employee emp = null;

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

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

```java
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"という文字列を返します。

```java: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の場合の代替文字列を指定することができます。

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

**Object.toString**

```java: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] (https://docs.oracle.com/javase/jp/9/docs/api/java/util/Objects.html)

## requireNonNullElse

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

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

```java
demo("obj1", "obj2");
// result : obj1

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

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

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

## requireNonNullElseGet

```java
public void demo2(String obj, Supplier<String> supplier) {
    String result = Objects.requireNonNullElseGet(obj, supplier);
    System.out.println("result : " + result);
}
```

```java
demo("obj1", () -> "obj2");
// result : obj1

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

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

## checkIndex

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

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

```java
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)の範囲内かチェックします。

```java
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]);
}
```

```java
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)の範囲内かチェックします。

```java
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]);
}
```

```java
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] (https://docs.oracle.com/javase/jp/10/docs/api/java/util/Objects.html)

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

# [Java 11で追加されたAPI] (https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Objects.html)

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

# [Java 12で追加されたAPI] (https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/util/Objects.html)

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

# [Java 13で追加されたAPI] (https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/Objects.html)

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

# [Java 14で追加されたAPI] (https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/Objects.html)

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


# その他のおさらいメモ

* [Java NIO2のおさらいメモ] (https://qiita.com/rubytomato@github/items/6880eab7d9c76524d112)
    * 2017年08月15日
* [Java Collections Frameworkのおさらいメモ] (https://qiita.com/rubytomato@github/items/554095ae21a2c36f131a)
    * 2017年08月30日
* [パッケージ java.time.temporal のおさらいメモ] (https://qiita.com/rubytomato@github/items/e9325dd46aa11f1b8e2e)
    * 2018年01月30日
* [クラス java.util.Optionalのおさらいメモ] (https://qiita.com/rubytomato@github/items/92ac7944c830e54aa03d)
    * 2018年03月22日