Penggunaan untuk Opsional

271

Setelah menggunakan Java 8 sekarang selama 6+ bulan atau lebih, saya cukup senang dengan perubahan API baru. Satu area yang saya masih belum percaya adalah kapan harus digunakan Optional. Saya tampaknya berayun di antara keinginan untuk menggunakannya di mana saja sesuatu mungkin terjadi null, dan tidak ada tempat sama sekali.

Tampaknya ada banyak situasi di mana saya bisa menggunakannya, dan saya tidak pernah yakin apakah itu menambah manfaat (keterbacaan / keamanan nol) atau hanya menyebabkan overhead tambahan.

Jadi, saya punya beberapa contoh, dan saya akan tertarik pada pemikiran masyarakat tentang apakah Optionalitu bermanfaat.

1 - Sebagai tipe pengembalian metode publik saat metode tersebut dapat kembali null:

public Optional<Foo> findFoo(String id);

2 - Sebagai parameter metode saat param mungkin null:

public Foo doSomething(String id, Optional<Bar> barOptional);

3 - Sebagai anggota opsional kacang:

public class Book {

  private List<Pages> pages;
  private Optional<Index> index;

}

4 - Dalam Collections:

Secara umum saya tidak berpikir:

List<Optional<Foo>>

menambahkan sesuatu - terutama karena seseorang dapat menggunakan filter()untuk menghapus nullnilai dll, tetapi apakah ada kegunaan yang baik untuk Optionalkoleksi?

Adakah kasus yang saya lewatkan?

Akan
sumber
2
Satu kasus yang menurut saya berguna adalah, misalnya, jika Anda memiliki peta substitusi. Misalnya Map<Character, String>. Jika tidak ada substitusi saya dapat menggunakan ini: Optional.ofNullable(map.get(c)).orElse(String.valueOf(c)). Perhatikan juga bahwa Opsional dicuri dari Guava dan memiliki sintaks yang jauh lebih baik:Optional.fromNullable(map.get(c)).or(String.valueOf(c));
fge
3
Juga, dalam koleksi, well, ada koleksi yang tidak mengizinkan nilai nol! Opsional sesuai dengan tagihan di sini. Dan Anda dapat .filter(Optional::absent)"
membatalkan
2
@fge Dalam semua keadilan, saya pikir konsep Opsional sebenarnya berasal dari FP.
VH-NZZ
2
@fge bukankah itu lebih baik diungkapkan dengan getOrDefault()?
Jim Garrison

Jawaban:

206

Poin utama Optionaladalah untuk menyediakan sarana untuk fungsi mengembalikan nilai untuk menunjukkan tidak adanya nilai kembali. Lihat diskusi ini . Ini memungkinkan pemanggil untuk melanjutkan serangkaian panggilan metode lancar.

Ini paling cocok dengan kasus penggunaan # 1 dalam pertanyaan OP. Meskipun, tidak adanya nilai adalah formulasi yang lebih tepat daripada nol karena sesuatu seperti IntStream.findFirsttidak pernah bisa mengembalikan nol.

Untuk use case # 2 , meneruskan argumen opsional ke suatu metode, ini bisa dibuat berfungsi, tapi agak canggung. Misalkan Anda memiliki metode yang mengambil string diikuti oleh string kedua opsional. Menerima Optionalsebagai argumen kedua akan menghasilkan kode seperti ini:

foo("bar", Optional.of("baz"));
foo("bar", Optional.empty());

Bahkan menerima null lebih baik:

foo("bar", "baz");
foo("bar", null);

Mungkin yang terbaik adalah memiliki metode kelebihan beban yang menerima argumen string tunggal dan menyediakan default untuk yang kedua:

foo("bar", "baz");
foo("bar");

Ini memang memiliki keterbatasan, tetapi jauh lebih bagus daripada yang di atas.

Gunakan case # 3 dan # 4 , memiliki Optionaldalam bidang kelas atau dalam struktur data, dianggap sebagai penyalahgunaan API. Pertama, itu bertentangan dengan tujuan desain utama Optionalseperti yang dinyatakan di atas. Kedua, itu tidak menambah nilai apa pun.

Ada tiga cara untuk menangani ketiadaan nilai dalam Optional: untuk memberikan nilai pengganti, memanggil fungsi untuk memberikan nilai pengganti, atau untuk melemparkan pengecualian. Jika Anda menyimpan ke dalam bidang, Anda akan melakukan ini pada inisialisasi atau waktu penugasan. Jika Anda menambahkan nilai ke dalam daftar, seperti yang disebutkan OP, Anda memiliki pilihan tambahan yaitu tidak menambahkan nilai, sehingga "mendatarkan" nilai-nilai yang tidak ada.

Saya yakin seseorang dapat membuat beberapa kasus yang dibuat-buat di mana mereka benar-benar ingin menyimpan Optionaldalam bidang atau koleksi, tetapi secara umum, yang terbaik adalah menghindari melakukan ini.

Stuart Marks
sumber
47
Saya tidak setuju dengan # 3. Dapat bermanfaat untuk memiliki Optionalsebagai bidang ketika hal-hal harus dilakukan atau tidak dilakukan pada ada atau tidak adanya nilai.
glglgl
15
Saya tidak melihat mengapa melakukan secara if(foo == null)internal akan lebih baik daripada hanya menyimpan bidang sebagai optional. Dan saya tidak melihat mengapa secara eksplisit memanggil getOptionalFoo()internal lebih baik daripada hanya menyimpan bidang sebagai Optional. Juga, jika satu bidang bisa nulldan satu bidang tidak bisa null, mengapa tidak mengomunikasikannya ke kompiler dengan membuatnya Optionalatau tidak Optional.
mogronalol
27
@StuartMarks, ini adalah salah satu hal yang membingungkan saya ketika saya mendengarnya dari semua Optional<>pakar: "jangan menyimpan Optional<>di lapangan". Saya benar-benar berusaha memahami inti dari rekomendasi ini. Pertimbangkan pohon DOM di mana simpul dapat memiliki orang tua atau tidak. Tampaknya dalam use case yang Node.getParent()akan kembali Optional<Node>. Apakah saya benar-benar diharapkan untuk menyimpan nulldan membungkus hasilnya setiap kali? Mengapa? Apa yang saya beli dari inefisiensi ekstra ini, selain membuat kode saya terlihat jelek?
Garret Wilson
7
@ GarretWilson Di sisi lain, misalkan Anda miliki Optional<Node> getParent() { return Optional.ofNullable(parent); }. Ini terlihat mahal karena mengalokasikan Optionalsetiap waktu! Tetapi jika penelepon membukanya segera, objek tersebut berumur pendek dan tidak pernah dipromosikan keluar dari ruang eden. Bahkan mungkin bisa dihilangkan dengan analisis pelarian JIT. Jawaban intinya adalah "itu tergantung" seperti biasa, tetapi menggunakan Optionaldi bidang berpotensi menggembungkan penggunaan memori dan memperlambat traversal struktur data. Dan akhirnya saya pikir itu mengacaukan kode, tapi ini masalah selera.
Stuart Marks
6
@ GarretWilson Jadi, apakah Anda menulis blog untuk itu? Saya akan tertarik dengan hal itu :)
akhil_mittal
78

Saya terlambat ke permainan tetapi untuk apa nilainya, saya ingin menambahkan 2 Cents saya. Mereka menentang tujuan desainOptional , yang dirangkum dengan baik oleh jawaban Stuart Marks , tapi saya masih yakin akan validitasnya (jelas).

Gunakan Opsional Di Mana Saja

Secara umum

Saya menulis seluruh posting blog tentang menggunakanOptional tetapi pada dasarnya turun ke ini:

  • rancang kelas Anda untuk menghindari opsionalitas jika memungkinkan
  • dalam semua kasus yang tersisa, standarnya adalah menggunakan Optionalalih-alihnull
  • mungkin membuat pengecualian untuk:
    • variabel lokal
    • mengembalikan nilai dan argumen ke metode pribadi
    • blok kode kritis kinerja (jangan tebak, gunakan profiler)

Dua pengecualian pertama dapat mengurangi persepsi overhead tentang membungkus dan membuka bungkus referensi Optional. Mereka dipilih sedemikian rupa sehingga nol tidak pernah bisa secara legal melewati batas dari satu instance ke instance lainnya.

Perhatikan bahwa ini hampir tidak akan pernah memungkinkan Optionaldalam koleksi yang hampir seburuk nulls. Tapi jangan lakukan itu. ;)

Mengenai pertanyaan Anda

  1. Iya.
  2. Jika kelebihan muatan bukan pilihan, ya.
  3. Jika pendekatan lain (subclassing, dekorasi, ...) tidak ada pilihan, ya.
  4. Kumohon tidak!

Keuntungan

Melakukan hal ini mengurangi keberadaan nulls di basis kode Anda, meskipun tidak membasmi mereka. Tapi itu bahkan bukan poin utama. Ada keuntungan penting lainnya:

Maksud Klarifikasi

Menggunakan Optionaldengan jelas menyatakan bahwa variabelnya, yah, opsional. Setiap pembaca kode atau konsumen API Anda akan dikalahkan secara langsung dengan fakta bahwa mungkin tidak ada apa-apa di sana dan bahwa pemeriksaan diperlukan sebelum mengakses nilainya.

Menghapus Ketidakpastian

Tanpa Optionalmakna suatu nullkejadian tidak jelas. Ini bisa berupa representasi hukum suatu negara (lihat Map.get) atau kesalahan implementasi seperti inisialisasi yang hilang atau gagal.

Ini berubah secara dramatis dengan penggunaan Optional. Di sini, sudah terjadinya dari nullmenandakan keberadaan bug. (Karena jika nilainya dibiarkan hilang, maka Optionalakan digunakan.) Ini membuat debugging pengecualian null pointer jauh lebih mudah karena pertanyaan tentang makna ini nullsudah dijawab.

Lebih Banyak Cek kosong

Sekarang tidak ada yang bisa nulllagi, ini bisa diberlakukan di mana-mana. Baik dengan anotasi, pernyataan atau cek biasa, Anda tidak perlu memikirkan apakah argumen ini atau tipe pengembalian itu bisa nol. Tidak bisa!

Kekurangan

Tentu saja, tidak ada peluru perak ...

Performa

Membungkus nilai-nilai (terutama primitif) menjadi contoh tambahan dapat menurunkan kinerja. Dalam loop ketat ini mungkin menjadi nyata atau bahkan lebih buruk.

Perhatikan bahwa kompiler mungkin dapat mengelak dari referensi tambahan untuk umur pendek Optionals. Di Jawa 10 jenis nilai lebih lanjut dapat mengurangi atau menghapus penalti.

Serialisasi

Optionaltidak serializable tetapi solusinya tidak terlalu rumit.

Invarian

Karena invarian tipe generik di Jawa, operasi tertentu menjadi rumit ketika tipe nilai aktual didorong ke argumen tipe generik. Contoh diberikan di sini (lihat "Polimorfisme parametrik") .

Nicolai
sumber
Kerugian lain (atau batasan) adalah bahwa Anda tidak dapat mengurutkan instance Opsional (xxx), meskipun Oracle jelas-jelas memberlakukan pembatasan itu dengan sengaja. Saya skeptis tentang kebijaksanaan memiliki kelas-kelas ini tersedia di mana mereka hanya boleh digunakan dalam keadaan tertentu, dan dengan asumsi pengembang akan melakukan hal yang benar. Memecahkan satu masalah dapat menyebabkan masalah lainnya. Mungkin harus ada peringatan kompiler untuk membantu pengembang ketika menggunakan kelas opsional (xxx) dengan cara yang "tidak diinginkan" (misalnya sebagai parameter metode, dalam koleksi, dalam konstruktor, dll.) Jika itu benar-benar bukan penggunaan yang dimaksudkan?
skomisa
Sekitar 4, opsional dalam koleksi: Ini terkadang berguna untuk menyimpan opsional dalam Lists. Ini adalah kasus ketika penting bahwa elemen tertentu terletak pada indeks tertentu, tetapi elemen tersebut dapat hadir atau tidak. Itu jelas dikomunikasikan oleh List<Optional<T>>tipe. Jika di sisi lain hanya penting objek yang merupakan anggota beberapa koleksi maka tidak ada gunanya.
Lii
3
Saya pikir use-case # 2 masih sangat dipertanyakan. Suatu cara Optionalyang diteruskan ke suatu metode bisa null. Jadi, apa yang telah Anda dapatkan? Sekarang Anda memiliki dua cek untuk dilakukan. Lihat stackoverflow.com/a/31923042/650176
David V
2
@ Davidvid melihat daftar kelebihan yang saya berikan - semuanya juga berlaku untuk kasus itu. Lagipula, jika Anda melakukan semuanya Optional(yang seharusnya menjadi masalah jika Anda bersedia memberikannya sebagai argumen) nulltidak pernah merupakan nilai hukum. Jadi memanggil metode dengan parameter eksplisit nulljelas merupakan kesalahan.
Nicolai
28

Secara pribadi, saya lebih suka menggunakan IntelliJ's Code Inspection Tool untuk menggunakan @NotNulldan @Nullablememeriksa karena ini sebagian besar waktu kompilasi (dapat memiliki beberapa pemeriksaan runtime) Ini memiliki overhead yang lebih rendah dalam hal pembacaan kode dan kinerja runtime. Ini tidak seketat menggunakan Opsional, namun kurangnya kekakuan ini harus didukung oleh tes unit yang layak.

public @Nullable Foo findFoo(@NotNull String id);

public @NotNull Foo doSomething(@NotNull String id, @Nullable Bar barOptional);

public class Book {

  private List<Pages> pages;
  private @Nullable Index index;

}

List<@Nullable Foo> list = ..

Ini berfungsi dengan Java 5 dan tidak perlu untuk membungkus dan membuka nilai. (atau buat objek pembungkus)

Peter Lawrey
sumber
7
Uhm, apakah itu anotasi IDEA? Saya lebih suka JSR 305 @Nonnullsecara pribadi - bekerja dengan FindBugs;)
fge
@fge Ada kekurangan standar dalam hal ini, tapi saya percaya alat-alat tersebut pada umumnya dapat dikonfigurasi dan Anda tidak harus berakhir dengan@Nonnull @NotNull etc
Peter Lawrey
4
Ya itu benar; IDEA (13.x) memberikan tiga pilihan berbeda ... Meh, saya selalu menggunakan JSR 305 anywa
fge
3
Saya tahu ini sudah tua, tetapi diskusi tentang anotasi & alat layak tautan ke stackoverflow.com/questions/35892063/... - yang secara spesifik membahas kasus Java 8.
Stephan Herrmann
25

Saya pikir Pilihan Guava dan halaman wiki mereka menempatkannya dengan cukup baik:

Selain peningkatan keterbacaan yang berasal dari pemberian nama nol, keuntungan terbesar dari Opsional adalah kebodohannya. Ini memaksa Anda untuk secara aktif memikirkan kasus yang tidak ada jika Anda ingin program Anda dikompilasi sama sekali, karena Anda harus secara aktif membuka Bungkusan Opsional dan menangani kasus itu. Null membuatnya mudah untuk melupakan hal-hal, dan meskipun FindBugs membantu, kami tidak berpikir itu mengatasi masalah hampir juga.

Ini sangat relevan ketika Anda mengembalikan nilai yang mungkin atau mungkin tidak "ada." Anda (dan orang lain) jauh lebih mungkin untuk melupakan yang lain. Metode (a, b) dapat mengembalikan nilai nol daripada Anda mungkin lupa bahwa a bisa menjadi nol ketika Anda menerapkan metode lain. Returning Optional membuat penelepon tidak mungkin melupakan kasing itu, karena mereka harus membuka sendiri objek untuk dikompilasi oleh kode mereka. - (Sumber: Guava Wiki - Menggunakan dan Menghindari null - Apa gunanya? )

Optionalmenambahkan beberapa overhead, tapi saya pikir keuntungan jelasnya adalah untuk membuatnya eksplisit bahwa suatu objek mungkin tidak ada dan itu memaksa bahwa programmer menangani situasi. Ini mencegah seseorang melupakan != nullcek yang dicintai .

Mengambil contoh 2 , saya pikir ini adalah kode yang jauh lebih eksplisit untuk ditulis:

if(soundcard.isPresent()){
  System.out.println(soundcard.get());
}

dari

if(soundcard != null){
  System.out.println(soundcard);
}

Bagi saya, semakin Optionalbaik menangkap fakta bahwa tidak ada kartu suara.

2 ¢ saya tentang poin Anda:

  1. public Optional<Foo> findFoo(String id);- Saya tidak yakin tentang ini. Mungkin saya akan mengembalikan Result<Foo>yang mungkin kosong atau mengandung Foo. Ini adalah konsep yang mirip, tetapi tidak benar-benar sebuah Optional.
  2. public Foo doSomething(String id, Optional<Bar> barOptional);- Saya lebih suka @Nullable dan cek findbugs, seperti dalam jawaban Peter Lawrey - lihat juga diskusi ini .
  3. Contoh buku Anda - Saya tidak yakin apakah saya akan menggunakan Opsional secara internal, yang mungkin tergantung pada kerumitannya. Untuk "API" buku, saya akan menggunakan a Optional<Index> getIndex()untuk secara eksplisit menunjukkan bahwa buku itu mungkin tidak memiliki indeks.
  4. Saya tidak akan menggunakannya dalam koleksi, bukan membiarkan nilai nol dalam koleksi

Secara umum, saya akan mencoba untuk meminimalkan melewati null. (Sekali terbakar ...) Saya pikir itu layak untuk menemukan abstraksi yang sesuai dan menunjukkan kepada sesama programmer apa nilai pengembalian tertentu sebenarnya mewakili.

Behe
sumber
15
Anda akan menulis soundcard.ifPresent(System.out::println). Panggilan isPresentsecara semantik sama dengan memeriksa null.
oliver yang lebih baik
Masalahnya bagi saya adalah bahwa hal-hal dengan tipe opsional masih bisa nol. Jadi untuk benar-benar aman, Anda harus melakukan sesuatu seperti if(soundcard != null && soundcard.isPresent()). Meskipun membuat api yang mengembalikan Opsional dan juga bisa mengembalikan nol adalah sesuatu yang saya harap tidak ada yang pernah melakukannya.
Simon Baumgardt-Wellander
"Itu memaksa Anda untuk secara aktif memikirkan kasus yang tidak ada jika Anda ingin program Anda dikompilasi sama sekali, karena Anda harus secara aktif membuka Bungkusan Opsional dan menangani kasus itu." Saya tidak begitu yakin bagaimana ini memaksa, meskipun saya tidak banyak bekerja di Jawa. Bisakah Anda menjelaskan apa yang dilakukan Java untuk memaksa Anda membuka dan memeriksa kasus! IsPresent hanya untuk dikompilasi?
naksir
15

Dari tutorial Oracle :

Tujuan dari Opsional bukan untuk menggantikan setiap referensi nol tunggal dalam basis kode Anda, tetapi untuk membantu merancang API yang lebih baik di mana — hanya dengan membaca tanda tangan suatu metode — pengguna dapat mengetahui apakah akan mengharapkan nilai opsional. Selain itu, Opsional memaksa Anda untuk secara aktif membuka Bungkusan Opsional untuk menangani ketiadaan nilai; sebagai hasilnya, Anda melindungi kode Anda terhadap pengecualian null pointer yang tidak diinginkan.

ctomek
sumber
3
API hanya untuk bagian pengembalian metode, kan? Opsional tidak boleh digunakan sebagai parameter karena tipe-erasure? kadang-kadang saya menggunakan Opsional secara internal dalam suatu metode, dikonversi dari parameter nullable atau sebagai bidang diinisialisasi dari parameter konstruktor nol ... masih mencoba mencari tahu apakah itu lebih berguna daripada hanya membiarkannya sebagai null - ada yang punya pemikiran?
ycomp
@ comp Anda dapat menemukan cukup banyak informasi tentang kasus-kasus ini dalam pertanyaan ini atau itu . Jawaban untuk pertanyaan-pertanyaan itu lebih dari apa yang ditanyakan dan mencakup kasus-kasus lain. Untuk info lebih lanjut, telusuri lebih banyak atau ajukan pertanyaan Anda sendiri, karena mungkin Anda tidak akan mendapatkan banyak perhatian di sini. ; )
ctomek
8

1 - Sebagai tipe pengembalian metode publik saat metode tersebut dapat mengembalikan nol:

Berikut ini adalah artikel bagus yang menunjukkan kegunaan usecase # 1. Ada kode ini

...
if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        Country country = address.getCountry();
        if (country != null) {
            String isocode = country.getIsocode();
            isocode = isocode.toUpperCase();
        }
    }
}
...

ditransformasikan ke ini

String result = Optional.ofNullable(user)
  .flatMap(User::getAddress)
  .flatMap(Address::getCountry)
  .map(Country::getIsocode)
  .orElse("default");

dengan menggunakan Opsional sebagai nilai balik metode pengambil masing-masing .

artifex
sumber
2

Berikut ini adalah penggunaan yang menarik (saya percaya) untuk ... Tes.

Saya berniat menguji salah satu proyek saya dan karena itu saya membangun pernyataan; hanya ada hal-hal yang harus saya verifikasi dan yang lain tidak.

Karena itu saya membangun hal-hal untuk menegaskan dan menggunakan pernyataan untuk memverifikasi mereka, seperti ini:

public final class NodeDescriptor<V>
{
    private final Optional<String> label;
    private final List<NodeDescriptor<V>> children;

    private NodeDescriptor(final Builder<V> builder)
    {
        label = Optional.fromNullable(builder.label);
        final ImmutableList.Builder<NodeDescriptor<V>> listBuilder
            = ImmutableList.builder();
        for (final Builder<V> element: builder.children)
            listBuilder.add(element.build());
        children = listBuilder.build();
    }

    public static <E> Builder<E> newBuilder()
    {
        return new Builder<E>();
    }

    public void verify(@Nonnull final Node<V> node)
    {
        final NodeAssert<V> nodeAssert = new NodeAssert<V>(node);
        nodeAssert.hasLabel(label);
    }

    public static final class Builder<V>
    {
        private String label;
        private final List<Builder<V>> children = Lists.newArrayList();

        private Builder()
        {
        }

        public Builder<V> withLabel(@Nonnull final String label)
        {
            this.label = Preconditions.checkNotNull(label);
            return this;
        }

        public Builder<V> withChildNode(@Nonnull final Builder<V> child)
        {
            Preconditions.checkNotNull(child);
            children.add(child);
            return this;
        }

        public NodeDescriptor<V> build()
        {
            return new NodeDescriptor<V>(this);
        }
    }
}

Di kelas NodeAssert, saya melakukan ini:

public final class NodeAssert<V>
    extends AbstractAssert<NodeAssert<V>, Node<V>>
{
    NodeAssert(final Node<V> actual)
    {
        super(Preconditions.checkNotNull(actual), NodeAssert.class);
    }

    private NodeAssert<V> hasLabel(final String label)
    {
        final String thisLabel = actual.getLabel();
        assertThat(thisLabel).overridingErrorMessage(
            "node's label is null! I didn't expect it to be"
        ).isNotNull();
        assertThat(thisLabel).overridingErrorMessage(
            "node's label is not what was expected!\n"
            + "Expected: '%s'\nActual  : '%s'\n", label, thisLabel
        ).isEqualTo(label);
        return this;
    }

    NodeAssert<V> hasLabel(@Nonnull final Optional<String> label)
    {
        return label.isPresent() ? hasLabel(label.get()) : this;
    }
}

Yang berarti pernyataan benar-benar hanya memicu jika saya ingin memeriksa labelnya!

Fge
sumber
2

Optionalkelas memungkinkan Anda menghindari menggunakan nulldan memberikan alternatif yang lebih baik:

  • Ini mendorong pengembang untuk melakukan pemeriksaan kehadiran agar tidak tertangkap NullPointerException.

  • API menjadi lebih baik didokumentasikan karena dimungkinkan untuk dilihat, di mana mengharapkan nilai yang tidak ada.

Optionalmenyediakan API yang nyaman untuk pekerjaan lebih lanjut dengan objek isPresent():; get(); orElse(); orElseGet(); orElseThrow(); map(); filter(); flatmap().

Selain itu, banyak kerangka kerja yang secara aktif menggunakan tipe data ini dan mengembalikannya dari API mereka.


sumber
2

Di java, jangan gunakan itu kecuali Anda kecanduan pemrograman fungsional.

Mereka tidak memiliki tempat sebagai argumen metode (saya menyarankan seseorang suatu hari akan memberikan Anda opsional nol, bukan hanya pilihan yang kosong).

Mereka masuk akal untuk nilai-nilai pengembalian tetapi mereka mengundang kelas klien untuk terus memperluas rantai pengembangan perilaku.

FP dan rantai memiliki sedikit tempat dalam bahasa imperatif seperti java karena membuatnya sangat sulit untuk di-debug, bukan hanya untuk membaca. Ketika Anda melangkah ke garis, Anda tidak bisa mengetahui keadaan atau niat program; Anda harus melangkah untuk mengetahuinya (ke dalam kode yang sering kali bukan milik Anda dan banyak bingkai tumpukan meskipun filter langkah) dan Anda harus menambahkan banyak breakpoints untuk memastikan itu bisa berhenti dalam kode / lambda yang Anda tambahkan, alih-alih hanya berjalan di jalur if / else / call trivial.

Jika Anda ingin pemrograman fungsional, pilih sesuatu yang lain daripada java dan harap Anda memiliki alat untuk debug itu.

pengguna2023577
sumber
1

Saya tidak berpikir bahwa Opsional adalah pengganti umum untuk metode yang berpotensi mengembalikan nilai nol.

Gagasan dasarnya adalah: Tidak adanya nilai tidak berarti bahwa nilai tersebut berpotensi tersedia di masa mendatang. Ini perbedaan antara findById (-1) dan findById (67).

Informasi utama Opsional untuk penelepon adalah bahwa ia mungkin tidak mengandalkan nilai yang diberikan tetapi mungkin tersedia pada suatu waktu. Mungkin itu akan menghilang lagi dan kembali lagi nanti. Ini seperti saklar on / off. Anda memiliki "opsi" untuk menghidupkan atau mematikan lampu. Tetapi Anda tidak memiliki pilihan jika Anda tidak memiliki lampu untuk menyala.

Jadi saya merasa terlalu berantakan untuk memperkenalkan Opsional di mana-mana di mana sebelumnya null berpotensi dikembalikan. Saya masih akan menggunakan null, tetapi hanya di area terbatas seperti akar pohon, inisialisasi malas dan metode pencarian eksplisit.

oopexpert
sumber
0

Tampaknya Optionalhanya berguna jika jenis T di Opsional adalah tipe primitif seperti int, long, char, dll Untuk "nyata" kelas, itu tidak masuk akal bagi saya karena Anda dapat menggunakan nullnilai pula.

Saya pikir itu diambil dari sini (atau dari konsep bahasa lain yang serupa).

Nullable<T>

Di C # ini Nullable<T>sudah lama diperkenalkan untuk membungkus tipe nilai.

peter.petrov
sumber
2
Hal ini ripoff dari jambu yang Optionalsebenarnya
FGE
2
@Fge OK tapi ketika ini hadir di C # (2005, MS.NET 2.0), tidak ada Jambu, saya pikir. Dan ... siapa yang tahu dari mana C # mengambil ini.
peter.petrov
3
@Fge "Ripoff of Guava's Optional" adalah semacam cara yang lucu untuk mengatakannya, karena orang-orang Guava berpartisipasi dalam diskusi, memberikan pengalaman mereka, dan umumnya mendukung java.util.Optional.
Stuart Marks
6
@fge Tidak diragukan lagi API Java sangat dipengaruhi oleh Guava. Saya menerima masalah dengan "ripoff" yang kedengarannya seperti mencuri. Orang-orang Guava menyumbangkan banyak ide berharga ke Jawa 8.
Stuart Marks
6
Anda tidak mengerti intinya. Opsional harus digunakan alih-alih mengembalikan nol. Ini lebih aman daripada berpotensi melempar NullPointerException. Lihat: oracle.com/technetwork/articles/java/…
Kilizo
0

Sebuah memiliki semantik yang mirip dengan sebuah contoh unmodifiable dari pola desain Iterator :Optional

  • itu mungkin atau mungkin tidak merujuk ke suatu objek (seperti yang diberikan oleh isPresent())
  • itu bisa dereferenced (menggunakan get()) jika itu merujuk ke suatu objek
  • tetapi tidak dapat maju ke posisi berikutnya dalam urutan (tidak memiliki next()metode).

Karena itu pertimbangkan untuk mengembalikan atau melewati Optionalkonteks di mana Anda sebelumnya mungkin telah mempertimbangkan menggunakan Java Iterator.

Raedwald
sumber
-1

Java SE 8 memperkenalkan kelas baru yang disebut java.util.Optional,

Anda dapat membuat Opsional kosong atau Opsional dengan nilai nol.

Optional<String> emptyOptional = Optional.empty(); 

Dan di sini adalah Opsional dengan nilai bukan nol:

String valueString = new String("TEST");
Optional<String> optinalValueString = Optional.of(valueString );

Lakukan Sesuatu Jika Suatu Nilai Hadir

Sekarang Anda memiliki objek opsional, Anda dapat mengakses metode yang tersedia untuk secara eksplisit menangani ada atau tidaknya nilai. Daripada harus ingat untuk melakukan cek nol, sebagai berikut:

String nullString = null;
if (nullString != null) {
    System.out.println(nullString);
}

Anda dapat menggunakan metode ifPresent (), sebagai berikut:

Optional<String> optinalString= null;
optinalString.ifPresent(System.out::println);

package optinalTest;

import java.util.Optional;

public class OptionalTest {
    public Optional<String> getOptionalNullString() {
        return null;
//      return Optional.of("TESt");
    }

    public static void main(String[] args) {

        OptionalTest optionalTest = new OptionalTest();

        Optional<Optional<String>> optionalNullString = Optional.ofNullable(optionalTest.getOptionalNullString());

        if (optionalNullString.isPresent()) {
            System.out.println(optionalNullString.get());
        }
    }
}
Kumar Abhishek
sumber
copypaste ini dimaksudkan untuk mendapatkan reputasi murah, tetapi tidak terkait dengan pertanyaan OP
stinger