Contoh penggunaan

Sekarang yang kita pelajari mengapa Optionals digunakan, mari kita lihat apa yang sebenarnya dapat kita lakukan dengannya di java. Contoh kode ini (dan Sponge) menggunakan java.util.Optional kelas tersedia di Java 8.

Mendapatkan Nilai terbungkus

The get() method will unwrap an Optional and return the wrapped value. If no value is present, calling get() will throw a NoSuchElementException, so a presence check should be performed first.

Optional<String> opt = getOptionalString();
String wrappedString = opt.get();

Gagal pada nilai absen

Tujuan dari tipe `` Opsional` mewakili nilai yang mungkin atau mungkin tidak ada di sana. Dengan demikian, banyak kasus penggunaan berkisar pada penanganan nilai absen.

Memeriksa Kehadiran

Metode `` isPresent () `` mengembalikan nilai true jika ada pada `` Opsional``. Ini bisa memberikan verifikasi yang paling dasar dan setara dengan cek klasik `` null``.

Optional<String> opt = getOptionalString();
if (opt.isPresent()) {
    String wrappedString = opt.get();
    // more code
}

Gunakan Nilai Default

Pola umum adalah yang jatuh kembali ke harga default jika tidak ada yang hadir. Metode orElse() mengizinkan laporan satu baris yang akan mengembalikan harga yang ada pada Optional atau harga default yang diberikan.

Melainkan

Optional<String> optionalString = optionalString();
String someString;
if (optionalString.isPresent()) {
    someString = optionalString.get();
} else {
    someString = DEFAULT_STRING;
}

gunakan saja

String someString = getOptionalString().orElse(DEFAULT_STRING);

Dalam beberapa kasus, nilai harus kembali dihitung dengan cara yang memiliki efek samping atau sangat mahal. Dalam kasus seperti ini, diinginkan untuk menghitung nilai kembali hanya jika diperlukan (* jarang evaluasi *). Metode `` orElseGet () `` menerima Pemasok `` bukan nilai yang telah dihitung sebelumnya. Jika tidak ada nilai pada `` Opsional`` itu sendiri, `` Pemasok`` akan dipanggil. Karena `` Pemasok` adalah antarmuka fungsional, lambda cepat atau referensi metode dapat dilewatkan.

Melainkan

Optional<String> optionalString = optionalString();
String someString;
if (optionalString.isPresent()) {
    someString = optionalString.get();
} else {
    someString = myPlugin.defaultString();
}

gunakan saja

String someString = getOptionalString().orElseGet(myPlugin::defaultString);

Gagal pada nilai absen

Jika nilai yang absen harus mengarah pada pengecualian, hampir selalu lebih baik untuk membuang pengecualian khusus alih-alih mengandalkan kembali `` NoSuchElementException``. Jika Anda memanggil metode `` orElseThrow () `` dengan `` Supplier``, itu akan mengembalikan nilai terbungkus jika ada, atau melempar `` Throwable`` yang diperoleh dari `` Supplier`` jika ` Opsional kosong Sekali lagi, sebagai `` Pemasok` adalah antarmuka fungsional, lambda cepat atau referensi metode dapat digunakan sebagai gantinya.

Melainkan

Optional<String> optionalString = optionalString();
if (!optionalString.isPresent()) {
    throw new MyException();
}
String someString = optionalString.get();

gunakan saja

String someString = getOptionalString().orElseThrow(MyException::new);

Catatan

Jika '' Throwable'' disediakan oleh pemasok diperiksa pengecualian, itu juga harus disertakan dalam tanda tangan dari fungsi sekitarnya (untuk contoh '' doStuff() Batal umum melempar MyException'')

Eksekusi Kode Bersyarat

Jika tidak ada nilai default yang bisa digunakan, kode yang bergantung pada nilai yang ada tidak bisa di eksekusi. Meskipun hal ini mungkin ditangani dalam kondisi sederhana, ada metode lain yang mudah digunakan.

Mengkonsumsi Nilai

Jika logika Anda untuk menangani nilai sekarang sudah dienkapsulasi dalam fungsi `` Konsumen`` atau fungsi satu parameter, metode `` ifPresent () `` akan menerima konsumen (atau referensi metode). Jika ada nilai pada `` Opsional`, maka akan diteruskan ke konsumen. Jika `` Opsional` kosong, tidak akan terjadi apa-apa.

Melainkan

Optional<String> optionalString = getOptionalString();
if (optionalString.isPresent()) {
    myPlugin.doSomethingWithString(optionalString.get());
}

gunakan saja

Optional<String> optionalString = getOptionalString();
optionalString.ifPresent(s -> myPlugin.doSomethingWithString(s));

atau

getOptionalString().ifPresent(myPlugin::doSomethingWithString);

Penyaringan

Hal ini juga mungkin untuk melewati sebuah '' predikat ''. Hanya nilai-nilai yang '' predikat '' ini mengembalikan true untuk akan disimpan. Jika tidak ada nilai hadir atau '' predikat '' kembali '' palsu '', kosong '' opsional '' akan dikembalikan. Karena metode ini mengembalikan opsional, memungkinkan untuk chaining dengan metode lain.

Melainkan

Optional<String> optionalString = getOptionalString();
if (optionalString.isPresent()) {
    String someString = optionalString.get();
    if (stringTester.isPalindromic(someString)) {
        myPlugin.doSomethingWithString(someString);
    }
}

gunakan saja

getOptionalString()
      .filter(stringTester::isPalindromic)
      .ifPresent(myPlugin::doSomethingWithString);

Catatan

Baik ini fungsi penyaringan atau fungsi pemetaan yang dijelaskan di bawah ini memodifikasi instance yang mereka dipanggil. Optionals selalu tidak berubah.

Pemetaan

Operasi berantai lainnya adalah pemetaan nilai potensial ke salah satu yang berbeda. Jika tidak ada nilai yang dihasilkan, tidak ada yang akan berubah. Namun jika ada, peta() metode akan kembali sebagai Opsional dari nilai yang dikembalikan dari Function seharusnya (atau Opsional kosong jika nilai yang dikembalikan adalah null).

Melainkan

Optional<String> optionalString = getOptionalString();
if (optionalString.isPresent()) {
    String someString = optionalString.toLowerCase();
    myPlugin.doSomethingWithString(someString);
}

gunakan saja

getOptionalString()
      .map(s -> s.toLowerCase())
      .ifPresent(myPlugin::doSomethingWithString);

Tip

Jika fungsi pemetaan Anda sudah mengembalikan `` Opsional``, gunakan metode `` flatMap () `` sebagai gantinya. Ini akan berperilaku seperti `` map () ``, kecuali bahwa mereka mengharapkan fungsi pemetaan untuk mengembalikan `` Opsional` dan karena itu tidak akan membungkus hasilnya.

Contoh Gabungan

Bayangkan sebuah plugin yang memungkinkan setiap pemain untuk memiliki hewan peliharaan berikut. Asumsikan adanya metode berikut:

  • `` petRegistry.getPetForPlayer () `` menerima `` Player`` dan mengembalikan sebuah `` Opsional <Pet> ``. Metode ini mencari hewan peliharaan yang terkait dengan pemain yang diberikan

  • `` petHelper.canSpawn () `` menerima `` Pet`` dan mengembalikan `` boolean``. Metode ini melakukan semua pemeriksaan yang diperlukan untuk memastikan hewan peliharaan yang diberikan bisa melahirkan.

  • `` petHelper.spawnPet () `` menerima `` Pet`` dan tidak mengembalikan apapun. Cara ini akan menelurkan hewan peliharaan yang sebelumnya tidak bertelur.

Sekarang dari suatu tempat (mungkin eksekusi perintah) kita mendapatkan variabel `` optionalPlayer` yang memegang Opsional <Player> . Kami sekarang ingin mendapatkan hewan peliharaan pemain ini, memeriksa apakah hewan peliharaan tersebut melahirkan dan jika tidak melahirkan, menelurkannya saat melakukan pemeriksaan yang sesuai jika masing-masing dan setiap `Opsional sebenarnya mengandung nilai. Kode hanya menggunakan metode `` isPresent () `` dan `` get () `` dasar menjadi sangat buruk dengan sangat cepat.

if (optionalPlayer.isPresent()) {
    Player player = optionalPlayer.get();
    Optional<Pet> optionalPet = petRegistry.getPetForPlayer(player);
    if (optionalPet.isPresent()) {
        Pet pet = optionalPet.get();
        if (petHelper.canSpawn(pet)) {
            petHelper.spawnPet(pet);
        }
    }
}

Namun dengan menggunakan metode `` Opsional` untuk metode eksekusi kode kondisional, semua pemeriksaan kehadiran tersembunyi, mengurangi tingkat boilerplate dan indentasi dan dengan demikian membiarkan kode lebih mudah dibaca:

optionalPlayer
      .flatMap(petRegistry::getPetForPlayer)
      .filter(petHelper::canSpawn)
      .ifPresent(petHelper::spawnPet);

Membuat Pilihan

Jika Anda memilih untuk memberikan API mengikuti kontrak yang sama dengan menggunakan `` Opsional` daripada mengembalikan nilai `` null``, Anda harus membuat `` Opsional`` untuk mengembalikannya. Hal ini dilakukan dengan memanggil salah satu dari tiga metode konstruktor statis.

`` Opsional.empty () `` akan selalu kembali kosong `` Opsional``.

`` Opsional.of () `` akan mengembalikan pembungkus opsional nilai yang diberikan dan meningkatkan `` NullPointerException`` jika nilainya `` null``.

`` Opsional.ofNullable () `` akan mengembalikan 'Opsional' kosong 'jika nilai yang diberikan adalah `` null``, jika tidak maka akan mengembalikan `` Opsional` `yang membungkus nilainya.