Java koleksiyonları çerçeve arayüzlerindeki SupportuppopOperationException


12

Java Koleksiyonlar Çerçevesi'ne baktığımda, arayüzlerin birkaçının yorum yaptığını fark ettim (optional operation). Bu yöntemler, UnsupportedOperationExceptionyalnızca bu yöntemi uygulamak istemiyorlarsa sınıfların uygulanmasına izin verir .

Bunun bir örneği, bir addAllyöntem Set Interface.

Şimdi, bu soru dizisinde belirtildiği gibi, arayüzler kullanımın ne bekleyebileceğine dair belirleyici bir sözleşmedir.

Arayüzler önemlidir, çünkü bir sınıfın yaptıklarını sınıfın yaptıklarından ayırırlar. Bir müşterinin ne bekleyebileceğini tanımlayan sözleşme, geliştiriciyi sözleşmeyi destekledikleri sürece uygulamayı istedikleri şekilde uygulamada serbest bırakır.

ve

Arayüz, bir nesnenin yapabileceği eylemlerin bir açıklamasıdır ... örneğin bir ışık anahtarını çevirdiğinizde, ışık yanar, nasıl olduğunu umursamazsınız, sadece yapar. Nesneye Yönelik Programlamada, Arayüz bir nesnenin "X" olması için sahip olması gereken tüm işlevlerin bir açıklamasıdır.

ve

Arayüz tabanlı yaklaşımın çok daha hoş olduğunu düşünüyorum. Daha sonra bağımlılıklarınızı güzel bir şekilde alay edebilirsiniz ve her şey temelde daha az sıkı bir şekilde birleştirilir.

Arayüzün anlamı nedir?

Arayüzler nelerdir?

Arayüz + Uzatma (mixin) ve Base Sınıf

Arayüzlerin amacının bir sözleşme tanımlamak ve bağımlılıklarınızı gevşek bir şekilde birleştirmek olduğu göz önüne alındığında, bazı yöntemlere sahip olmak bir UnsupportedOperationExceptiontür yenilgiyi atmaz mı? Bu artık geçirilemediğim Setve sadece kullanamayacağım anlamına geliyor addAll. Bunun yerine, hangi uygulamanın uygulandığımı bilmek zorundayım Set, böylece kullanıp kullanamayacağımı öğrenebilirim addAll. Bu benim için oldukça değersiz görünüyor.

Peki anlamı UnsupportedOperationExceptionnedir? Sadece eski kodları telafi ediyor mu ve arayüzlerini temizlemeleri mi gerekiyor? Yoksa özlediğim daha duygusal bir amacı var mı?


Ben kullandığınız hangi JRE bilmiyorum ama benim Oracle sürüm 8 tanımlamaz addAlliçinde HashSet. Bu varsayılan uygulanmasına defers AbstractCollectionkesinlikle gelmez ki değil atmak UnsupportedOperationException.

@ Haklısın haklısın. Belgeleri özledim. Sorumu düzenleyeceğim.
MirroredFate

1
Eclipse başlatmak ve doğru olduğundan emin olmak için kod başvuruları ve tanımları etrafında sıçrayan kaynak koduna bakmak istiyorum. JRE bağlantılı olduğu src.zipsürece harika çalışıyor. JRE'nin bazen hangi kodu çalıştırdığını tam olarak bilmeye yardımcı olur ve biraz ayrıntılı olabilen JavaDoc'a ertelemeyin.

Yanıtlar:


12

Aşağıdaki arayüzlere bakın:

Bu arayüzlerin tümü mutasyon yöntemlerini isteğe bağlı olarak beyan eder . Bu, örtük olarak Collections sınıfının değişmez olan bu arabirimlerin uygulamalarını döndürebildiğini belgelemektedir : yani, isteğe bağlı mutasyon işlemlerinin başarısız olacağı garanti edilmektedir. Bununla birlikte, JavaDoc'taki sözleşme uyarınca, bu arayüzlerin tüm uygulamaları okuma işlemlerine izin vermelidir. Buna "normal" uygulamalar HashSetve LinkedListaynı zamanda içindeki değişmez ambalajlar da dahildir Collections.

Kuyruk arayüzleriyle kontrast:

Bunlar arayüz yapmak değil isteğe bağlı herhangi işlemleri belirtmek: Kuyruğu, tanımı gereği, bir FIFO şekilde teklif ve anket elemanları için tasarlanmıştır. Değişmez bir kuyruk, tekerleksiz bir araba kadar faydalıdır.


Tekrar tekrar ortaya çıkan ortak bir fikir, hem değişebilen hem de değişmeyen nesnelere sahip bir miras hiyerarşisine sahip olmaktır. Ancak bunların hepsinin dezavantajları vardır. Karmaşıklık, problemi çözmeden suları çamurlaştırır.

  • Bir varsayım Setokuma işlemlerine sahip olabilir ve bir alt arayüz MutableSetyazma işlemlerine sahip olabilir. Liskov bize a'nınMutableSet ihtiyacı olan her şeye aktarılabileceğini söyler Set. İlk başta bu iyi görünüyor, ancak okuma sırasında temel kümenin değiştirilmeyeceğini bekleyen bir yöntem düşünün: iki iş parçacığının aynı seti kullanması ve setin değişmezini ihlal etmesi mümkün olacaktır. Bu, örneğin bir yöntem kümeden bir öğeyi iki kez okursa ve ilk kez orada bulunur, ancak ikinci kez değilse, soruna neden olabilir.

  • Setyerine sahip, doğrudan uygulamaları olabilir MutableSetve ImmutableSetdaha sonra sınıfları uygulamak için kullanılan subinterfaces olarak. Bu, yukarıdakiyle aynı soruna sahiptir: hiyerarşinin bir noktasında, bir arabirimin çakışan değişmezleri vardır. Biri "bu küme değiştirilebilir olmalı", diğeri "bu küme değişemez" diyor.

  • Değişken ve değişmez veri yapıları için tamamen ayrı iki hiyerarşi olabilir. Bu , çok az kazanç olan şey için bir ton ekstra karmaşıklık ekler . Bu aynı zamanda değişebilirliği umursamayan yöntemlerin belirli bir zayıflığına sahiptir (örneğin, sadece bir liste yinelemek istiyorum) şimdi iki ayrı arabirimi desteklemelidir. Java statik olarak yazıldığından, her iki arabirim hiyerarşisini işlemek için ek yöntemler anlamına gelir.

  • Tek bir arayüze sahip olabilir ve bir yöntem uygulanabilir değilse uygulamaların istisnalar atmasına izin verebiliriz. Java'nın izlediği yol budur ve en mantıklı olanıdır. Arabirim sayısı minimumda tutulur ve değiştirilemez değişmezler yoktur çünkü belgelenmiş arabirim her iki şekilde de değişebilirlik konusunda hiçbir garanti vermez . Değişmezlik değişmezi gerekiyorsa, içindeki sarıcıları kullanın Collections. Bir yöntemin bir koleksiyonu değiştirmesi gerekmiyorsa, yalnızca değiştirmeyin. Dezavantajı, bir yöntem dışarıdan bir koleksiyon sağlanmışsa, bir koleksiyonun başka bir iş parçacığında değişmeyeceğini garanti edemez, ancak yine de arama yönteminin (veya arama yönteminin) bir endişesidir.


İlgili okuma: Java 8 neden değiştirilemez koleksiyonlar içermiyor?


1
Ancak yöntemler isteğe bağlıysa, arayüzde yeri nedir? Örneğin isteğe bağlı yöntemleri içeren ayrı bir arayüz olmamalı mı MutableCollection?
MirroredFate

Hayır. Değişken ve değişmez nesnelere aynı hiyerarşide anlamlı bir şekilde sahip olmanın bir yolu yoktur. Yakın zamanda, karmaşıklığı ve bunun neden kötü bir fikir olduğunu açıklayan iyi bir diyagramı olan bir soru vardı, ancak siliniyor. Belki başka biri bunu açıklamaya yardımcı olacak bir soru biliyor, hiçbir şey bulamıyorum. Ama cevabımı biraz açıklamak için güncelleyeceğim.

Bu değişmez kuyruklar hakkında geniş bir açıklama. Birkaç gün önce bu sorunu çözmek için bir tane kullandım .
Karl Bielefeldt

@Karman Ama bu değişebilir ve değişmez nesneleri birbirlerinin karşıtları olarak görüyor. Bence değişmez nesne gerçekten sadece değişme yeteneğine sahip olmayan nesnelerdir. Dürüst olmak gerekirse, şu anki şekli daha karmaşık ve karışıktır, çünkü değişebilir bir uygulama nedir ve ne olmadığını anlamanız gerekir. Bana öyle geliyor ki, değişebilir yöntemleri ayırmak yerine tüm yöntemleri bir arayüze koyma arasındaki tek fark açıklıktır.
MirroredFate

@MirroredFate en son düzenlememi okudu.

2

Temelde YAGNI. Standart kütüphanedeki tüm somut koleksiyonlar değiştirilebilir, isteğe bağlı işlemleri uygular veya devralır. Genel amaçlı değişmez koleksiyonları umursamıyorlar ve Java geliştiricilerinin büyük çoğunluğu da ummuyorlar. Sadece değişmez koleksiyonlar için tam bir arayüz hiyerarşisi oluşturmayacaklar, daha sonra herhangi bir uygulama içermeyecekler.

Öte yandan, boş küme ve nCopies gibi değişmez olarak çok yararlı olabilecek birkaç özel amaçlı değer veya "sanal" koleksiyon vardır . Ayrıca, mevcut Java kodunu çağırmak isteyebilecek üçüncü taraf değişmez koleksiyonlar (Scala gibi) vardır, bu nedenle değişmez koleksiyonların en az yıkıcı şekilde açık olmalarını bıraktılar.


Tamam, bu biraz mantıklı. Yine de soruna yanlış yönden yaklaşıyor gibi görünüyor. Değişmez toplama arayüzleri tanımlayıp neden değişebilir toplama uygulamaları için değiştirilebilir arayüzler tanımlamaya başlamıyorsunuz?
MirroredFate
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.