なぜOptional
には、パブリックコンストラクターの代わりにof()
やofNullable()
のようなメソッドがあるのですか?
Joshua Blochの効果的なJavaから、第2章オブジェクトの作成と破棄、1項目:
コンストラクターではなく静的ファクトリーメソッドを検討する
どうして?
静的ファクトリメソッドの利点の1つは、コンストラクタとは異なり、メソッドに名前があることです。
静的ファクトリメソッドを使用すると、メソッド定義でインスタンス化の動作を指定できます。これにより、APIが使いやすくなり、クライアントが間違ったコンストラクターを呼び出すのを防ぎます。
例:In Optional.ofNullable
-> オプション 、 Optional.of
null値は許可されず、例外をスローします。ここではコンストラクタを使用できませんでした。
private Optional(T value) {
this.value = Objects.requireNonNull(value); //this throws NullPointerException
}
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
もう1つの利点(既に言及):
静的ファクトリメソッドの2番目の利点は、コンストラクタとは異なり、呼び出されるたびに新しいオブジェクトを作成する必要がないことです。
「オプション」では、空の値は一度だけインスタンス化され、静的フィールドに格納されます。この値は、プログラムで空の値が必要な場合に常に再利用されます。
private static final Optional<?> EMPTY = new Optional<>(); //instantiate value when program starts
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY; //return stored value when requested
return t;
}
理由は実際には非常に単純です。空のオプションは、メモリ効率を高めるための静的定数です。コンストラクターを使用した場合、一般的なケースでは毎回新しいインスタンスを作成する必要があります。
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
オプションは Value-based Class コンストラクタなし
アクセス可能なコンストラクターはありませんが、代わりに返されたインスタンスのIDに関してコミットメントを行わないファクトリーメソッドを通じてインスタンス化されます
可能性のあるインスタンス化のケースがわかっている場合、ファクトリメソッドはパブリックコンストラクターよりも優先されるべきです。
APIをクライアントクラスで使いやすくします。
ファクトリメソッドに加えて、呼び出しごとにインスタンスを作成するかどうかを決定できます。Optional.empty()
の場合、値は不変なのでキャッシュするのが理にかなっています。