Null参照の発明は10億ドルの損失
2009年のカンファレンスでNull参照を発明したことについて謝罪している。[10][11] それは10億ドルにも相当する私の誤りだ。null参照を発明したのは1965年のことだった。当時私はオブジェクト指向言語 (ALGOL W) における参照のための包括的型システムを設計していた。目標はコンパイラでの自動チェックで全ての参照が完全に安全であることを保証することだった。しかし、私は単にそれが容易だというだけで、無効な参照を含める誘惑に抵抗できなかった。これは後に数え切れない過ち、脆弱性、システムクラッシュを引き起こし、過去40年間で10億ドル相当の苦痛と損害を引き起こしたとみられる。 http://goo.gl/SjpucB
nullチェックしているのと変わらない
if(product.isPresent()) {
return product.price();
} else {
return 0;
}
nullチェックではなく、null時の振る舞いを記述する
//値がなければデフォルト値を返す
return product.orElse(0);
//値がなければ例外
return product.orElseThrow(() -> new RuntimeException("金額未設定"));
値がないと NoSuchElementException がスローされる
return product.get();
Java8まではnullを意識せざるを得ない
public boolean validatedZipFormat(String zip){
//引数のnullチェックしないとね
return isNotEmpty(zip)
&& zip.matches("^[0-9]{3}-[0-9]{4}$")
Java8からはnullを意識しなくてよい
public boolean validateZipFormat(String zip){
return Optional.ofNullable(zip)
.filter(num -> num.matches("^[0-9]{3}-[0-9]{4}$")) //matchしたらmatch文字列が返却され、matchしなければnull
.isPresent();
}
Java8まではnullを意識せざるを得ない
@Test
public void beforeJava8() throws Exception {
final String nullかも = "";
assertThat(someFunction(nullかも), is(nullValue()));
}
//なんらかの関数
private String someFunction(final String str) {
//こう書きたい、でもsomeNullableFuction()がnullを返却した場合には、NullPointerException
//return someNullableFuction2(str).toUpperCase();
//仕方ないのでnullチェックする
final String str2 = someNullableFuction(str);
return isNotEmpty(str2) ? str2.toUpperCase() : null;
}
//null返却もあり得る関数
private String someNullableFuction(final String str) {
return isEmpty(str) ? null : str;
}
Java8からは(Optionalの中では)nullを意識しなくてよい
@Test
public void afterJava8() throws Exception {
final String nullかも = "";
assertThat(someOptionalFunction(nullかも), is(nullValue()));
}
//なんらかの関数
private String someOptionalFunction(final String str) {
//Optionalの中で処理する
return Optional.ofNullable(str)
.map(st -> someNullableFuction(st)) //emptyなOptionalが返却される
.map(st -> st.toUpperCase()) //NullPointerExceptionが発生しない
.orElse(null);
}
//null返却もあり得る関数
private String someNullableFuction(final String str) {
return isEmpty(str) ? null : str;
}
Optionalの中ではnullを意識しなくて良いというは、連続する処理がすべてOptionalのコンテキストを保っているため。
コンテキストを保ったまま、処理を続けられる仕組みをモナドという。 モナドに関しては後日。
何かの条件で抽出して元の値を返す
@Test
public void testFilter() throws Exception {
final Integer empId = 444;
final Predicate<Integer> 特殊なひとたち = id -> id >= 1000 && id < 2000;
assertThat(特定の社員かどうか(empId, 特殊なひとたち), is(false));
}
//特定の社員かどうかをフィルタする関数
private boolean 特定の社員かどうか(final Integer empId, final Predicate<Integer> predicate) {
return Optional.ofNullable(empId)
.filter(predicate)
.isPresent();
}
何か処理して戻り値を返す
String str = "nullかもしれない文字列"
Integer length = Optional.ofNullable(str)
.map(s -> s.length())
.orElse(0);