Antarmuka kerangka kerja koleksi java di unsupportedOperationException

12

Melihat melalui Java Collections Framework, saya perhatikan beberapa antarmuka memiliki komentar (optional operation). Metode-metode ini memungkinkan kelas implementasi melalui UnsupportedOperationExceptionjika mereka tidak ingin mengimplementasikan metode itu.

Contoh dari ini adalah addAllmetode dalam Set Interface.

Sekarang, seperti yang dinyatakan dalam rangkaian pertanyaan ini, antarmuka adalah kontrak yang menentukan untuk apa yang bisa digunakan oleh penggunaan.

Antarmuka penting karena mereka memisahkan apa yang dilakukan kelas dari bagaimana melakukannya. Kontrak yang mendefinisikan apa yang dapat diharapkan klien membuat pengembang bebas menerapkannya dengan cara apa pun yang mereka pilih, selama mereka menegakkan kontrak.

dan

Antarmuka adalah deskripsi tindakan yang dapat dilakukan suatu objek ... misalnya ketika Anda membalik sakelar lampu, lampu menyala, Anda tidak peduli bagaimana, hanya saja fungsinya. Dalam Pemrograman Berorientasi Objek, Interface adalah deskripsi dari semua fungsi yang harus dimiliki suatu objek agar menjadi "X".

dan

Saya pikir pendekatan berbasis antarmuka secara signifikan lebih baik. Anda kemudian dapat mengejek dependensi Anda dengan baik, dan semuanya pada dasarnya kurang erat.

Apa gunanya antarmuka?

Apa itu interface?

Antarmuka + Ekstensi (mixin) vs Kelas Dasar

Mengingat bahwa tujuan dari antarmuka adalah untuk menentukan kontrak dan membuat dependensi Anda digabungkan secara longgar, tidakkah ada beberapa metode yang melemparkan UnsupportedOperationExceptionsemacam kekalahan tujuannya? Itu berarti saya tidak bisa lagi menggunakan Setdan hanya menggunakan addAll. Sebaliknya, saya harus tahu implementasi apa yang Setsaya lewati, jadi saya bisa tahu apakah saya bisa menggunakan addAllatau tidak. Bagi saya itu sepertinya tidak berharga.

Jadi apa gunanya UnsupportedOperationException? Apakah ini hanya untuk mengganti kode lama, dan mereka perlu membersihkan antarmuka mereka? Atau apakah itu memiliki tujuan yang lebih masuk akal yang saya lewatkan?

Mirrored Fate
sumber
Aku tidak tahu mana JRE Anda gunakan, tapi saya Oracle versi 8 tidak mendefinisikan addAlldi HashSet. Itu mengacu pada implementasi default di AbstractCollectionmana pasti tidak membuang UnsupportedOperationException.
@Snowman Anda benar. Saya salah membaca dokumen. Saya akan mengedit pertanyaan saya.
MirroredFate
1
Saya suka memulai Eclipse dan melihat kode sumber, memantul sekitar referensi kode dan definisi untuk memastikan saya sudah benar. Selama JRE ditautkan, src.zipia bekerja dengan baik. Ini membantu untuk mengetahui persis kode apa yang JRE jalankan kadang-kadang dan tidak tunduk pada JavaDoc yang bisa sedikit bertele-tele.

Jawaban:

12

Lihatlah antarmuka berikut:

Semua antarmuka ini menyatakan metode mutasi sebagai opsional. Ini secara implisit mendokumentasikan fakta bahwa kelas Collections mampu mengembalikan implementasi dari antarmuka yang tidak dapat diubah: yaitu, operasi-operasi mutasi opsional dijamin gagal. Namun, sesuai kontrak dalam JavaDoc, semua implementasi antarmuka tersebut harus mengizinkan operasi baca. Ini termasuk implementasi "normal" seperti HashSetdan LinkedListjuga pembungkus abadi di Collections.

Berbeda dengan antarmuka antrian:

Antarmuka ini tidak menentukan operasi opsional: antrian, menurut definisi, dirancang untuk menawarkan dan mem-polling elemen dengan cara FIFO. Antrian abadi sama bermanfaatnya dengan mobil tanpa roda.


Satu gagasan umum yang muncul berulang kali adalah memiliki hierarki warisan yang memiliki objek yang dapat berubah dan tidak dapat diubah. Namun, semua ini memiliki kekurangan. Kompleksitas membuat air berlumpur tanpa benar-benar menyelesaikan masalah.

  • Hipotetis Setdapat memiliki operasi baca, dan subinterface MutableSetdapat memiliki operasi tulis. Liskov memberi tahu kita bahwa a MutableSetkemudian dapat diteruskan ke apa pun yang membutuhkan a Set. Pada awalnya ini terdengar baik-baik saja, tetapi pertimbangkan metode yang mengharapkan set yang mendasarinya tidak akan dimodifikasi saat membaca: akan ada kemungkinan untuk dua utas menggunakan set yang sama dan melanggar invarian set yang tidak berubah. Ini dapat menyebabkan masalah misalnya jika suatu metode membaca elemen dari set dua kali dan itu ada di sana pertama kali tetapi tidak kedua kalinya.

  • Setbisa tidak memiliki implementasi langsung, sebaliknya memiliki MutableSetdan ImmutableSetsebagai subinterfaces yang kemudian digunakan untuk mengimplementasikan kelas. Ini memiliki masalah yang sama seperti di atas: pada beberapa titik dalam hierarki, antarmuka memiliki invarian yang saling bertentangan. Yang satu mengatakan "set ini harus bisa berubah" dan yang lain mengatakan "set ini tidak dapat berubah."

  • Mungkin ada dua hierarki yang benar-benar terpisah untuk struktur data yang bisa berubah dan tidak berubah. Ini menambahkan satu ton kompleksitas ekstra untuk apa yang akhirnya menjadi sangat sedikit keuntungan. Ini juga memiliki kelemahan spesifik dari metode yang tidak peduli tentang mutabilitas (misalnya saya hanya ingin mengulang daftar) sekarang harus mendukung dua antarmuka yang terpisah. Karena Java diketik secara statis, ini berarti metode tambahan untuk menangani kedua hierarki antarmuka.

  • Kami dapat memiliki satu antarmuka dan memungkinkan implementasi untuk melemparkan pengecualian jika suatu metode tidak berlaku untuk itu. Ini adalah rute yang diambil Jawa, dan itu paling masuk akal. Jumlah antarmuka dijaga agar tetap minimum, dan tidak ada invarian mutabilitas karena antarmuka yang terdokumentasi tidak memberikan jaminan tentang mutabilitas . Jika invarian kekekalan diperlukan, gunakan pembungkus di Collections. Jika suatu metode tidak perlu mengubah koleksi, cukup jangan mengubahnya. Kekurangannya adalah metode yang tidak dapat menjamin koleksi tidak akan berubah di utas lain jika disediakan koleksi dari luar, tetapi itu tetap merupakan masalah metode panggilan (atau metode panggilannya).


Bacaan terkait: Mengapa Java 8 tidak menyertakan koleksi tidak berubah?

Komunitas
sumber
1
Tetapi jika metode bersifat opsional, tempat apa yang mereka miliki di antarmuka? Bukankah seharusnya ada antarmuka terpisah yang berisi metode opsional, misalnya MutableCollection?
MirroredFate
Tidak. Tidak ada cara untuk memiliki objek yang bisa berubah dan tidak berubah dalam hierarki yang sama dengan cara yang berarti. Ada pertanyaan baru-baru ini yang memiliki diagram yang baik yang menunjukkan kompleksitas dan penjelasan mengapa itu adalah ide yang buruk, tetapi itu dihapus. Mungkin orang lain mengetahui pertanyaan untuk membantu menjelaskan hal ini, saya tidak dapat menemukan apa pun. Tetapi saya akan memperbarui jawaban saya untuk menjelaskan sedikit.
Itu semacam pernyataan luas tentang antrian yang tidak bisa diubah. Saya menggunakan satu hanya beberapa hari yang lalu untuk menyelesaikan masalah ini .
Karl Bielefeldt
@Snowman Tapi itu tampaknya menjadikan benda-benda yang bisa berubah dan tidak bisa berubah itu sebagai lawan satu sama lain. Saya pikir objek abadi benar-benar hanya objek yang tidak memiliki kemampuan untuk bermutasi. Jujur saja, seperti sekarang ini lebih kompleks dan kacau, karena Anda harus mencari tahu apa yang bisa diterapkan dan apa yang tidak. Menurut saya satu-satunya perbedaan antara menempatkan semua metode dalam satu antarmuka sebagai lawan untuk membagi metode yang bisa diubah adalah salah satu yang jelas.
MirroredFate
@MirroredFate membaca hasil edit terbaru saya.
2

Ini pada dasarnya YAGNI. Semua koleksi konkret di perpustakaan standar bisa berubah, menerapkan atau mewarisi operasi opsional. Mereka tidak peduli tentang koleksi abadi untuk tujuan umum dan begitu pula sebagian besar pengembang Java. Mereka tidak akan membuat hierarki antarmuka keseluruhan hanya untuk koleksi yang tidak dapat diubah, kemudian tidak menyertakan implementasi apa pun.

Di sisi lain, ada beberapa nilai tujuan khusus atau koleksi "virtual" yang bisa sangat berguna sebagai tidak berubah, seperti set kosong , dan nCopies . Juga, ada koleksi abadi pihak ketiga (seperti milik Scala), yang mungkin ingin memanggil kode Java yang ada, sehingga mereka membiarkan kemungkinan koleksi tidak tetap terbuka dengan cara yang paling tidak mengganggu.

Karl Bielefeldt
sumber
Ok, itu masuk akal. Namun sepertinya masih mendekati masalah dari arah yang salah. Mengapa tidak memulai dengan mendefinisikan antarmuka koleksi yang tidak bisa diubah, dan kemudian mendefinisikan antarmuka yang bisa diubah untuk implementasi koleksi yang bisa diubah?
MirroredFate