Metody opcjonalne w interfejsie Java

120

Z mojego zrozumienia, jeśli implementujesz interfejs w java, metody określone w tym interfejsie muszą być używane przez podklasy implementujące wspomniany interfejs.

Zauważyłem, że w niektórych interfejsach, takich jak interfejs Collection, istnieją metody, które są komentowane jako opcjonalne, ale co to dokładnie oznacza? Trochę mnie to rzuciło, bo myślałem, że wszystkie metody określone w interfejsie będą wymagane?

mjsey
źródło
Do jakich metod się odwołujesz? Nie mogę go znaleźć w JavaDoc ani w kodzie źródłowym
dcpomero
możliwy duplikat Co oznacza „operacja opcjonalna” w Javadoc na przykład Set # add (E)?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Odpowiedzi:

232

Wydaje się, że w odpowiedziach jest strasznie dużo niejasności.

Język Java wymaga, aby każda metoda interfejsu była implementowana przez każdą implementację tego interfejsu. Kropka. Nie ma wyjątków od tej zasady. Powiedzenie „Kolekcje są wyjątkiem” sugeruje bardzo niejasne zrozumienie tego, co się tutaj naprawdę dzieje.

Ważne jest, aby zdać sobie sprawę, że istnieją dwa poziomy dostosowania się do interfejsu:

  1. Co może sprawdzić język Java. To właściwie sprowadza się do: czy jest jakaś implementacja dla każdej z metod?

  2. Faktycznie wywiązuje się z umowy. To znaczy, czy implementacja robi to, co dokumentacja interfejsu mówi, że powinna?

    Dobrze napisane interfejsy będą zawierać dokumentację wyjaśniającą dokładnie, czego oczekuje się od implementacji. Twój kompilator nie może tego sprawdzić za Ciebie. Musisz przeczytać dokumenty i robić to, co mówią. Jeśli nie zrobisz tego, co mówi umowa, będziesz mieć implementację interfejsu, jeśli chodzi o kompilator , ale będzie to wadliwa / nieprawidłowa implementacja.

Projektując API Collections, Joshua Bloch zdecydował, że zamiast bardzo drobnoziarnistych interfejsów rozróżniać różne warianty kolekcji (np. Czytelne, zapisywalne, o swobodnym dostępie itp.), Będzie miał tylko bardzo zgrubny zestaw interfejsów, głównie Collection, List, Seti Map, a następnie udokumentować niektórych operacji jako „opcjonalne”. Miało to na celu uniknięcie kombinatorycznej eksplozji, która wynikałaby z drobnoziarnistych interfejsów. Z często zadawanych pytań dotyczących projektowania interfejsu API kolekcji Java :

Aby zilustrować problem szczegółowo, załóżmy, że chcesz dodać pojęcie modyfikowalności do Hierarchii. Potrzebujesz czterech nowych interfejsów: ModifiableCollection, ModifiableSet, ModifiableList i ModifiableMap. To, co wcześniej było prostą hierarchią, jest teraz chaotyczną heterarchią. Potrzebny jest również nowy interfejs Iteratora do użytku z kolekcjami niemodyfikowalnymi, który nie zawiera operacji usuwania. Czy możesz teraz pozbyć się wyjątku UnsupportedOperationException? Niestety nie.

Rozważ tablice. Implementują większość operacji List, ale nie usuwają i nie dodają. Są to listy o stałym rozmiarze. Jeśli chcesz uchwycić to pojęcie w hierarchii, musisz dodać dwa nowe interfejsy: VariableSizeList i VariableSizeMap. Nie musisz dodawać VariableSizeCollection i VariableSizeSet, ponieważ byłyby one identyczne z ModifiableCollection i ModifiableSet, ale możesz je dodać mimo wszystko ze względu na spójność. Ponadto potrzebujesz nowej odmiany ListIterator, która nie obsługuje operacji dodawania i usuwania, aby współpracować z niemodyfikowalną Listą. Teraz mamy do dziesięciu lub dwunastu interfejsów plus dwa nowe interfejsy Iteratora zamiast naszych oryginalnych czterech. Skończyliśmy? Nie.

Weź pod uwagę dzienniki (takie jak dzienniki błędów, dzienniki kontroli i kroniki dla odtwarzalnych obiektów danych). Są to naturalne sekwencje tylko do dołączania, które obsługują wszystkie operacje List z wyjątkiem usuwania i ustawiania (zastępowania). Wymagają nowego podstawowego interfejsu i nowego iteratora.

A co z niezmiennymi kolekcjami w przeciwieństwie do niemodyfikowalnych? (tj. kolekcje, których klient nie może zmienić ORAZ nigdy nie ulegną zmianie z żadnego innego powodu). Wielu twierdzi, że jest to najważniejsza różnica ze wszystkich, ponieważ umożliwia wielu wątkom jednoczesny dostęp do kolekcji bez konieczności synchronizacji. Dodanie tej obsługi do hierarchii typów wymaga czterech dodatkowych interfejsów.

Teraz mamy około dwudziestu interfejsów i pięciu iteratorów i jest prawie pewne, że w praktyce wciąż pojawiają się kolekcje, które nie pasują do żadnego z interfejsów. Na przykład widoki kolekcji zwrócone przez Map są kolekcjami tylko do naturalnego usuwania. Istnieją również kolekcje, które odrzucają pewne elementy na podstawie ich wartości, więc nadal nie wyeliminowaliśmy wyjątków w czasie wykonywania.

Kiedy wszystko zostało już powiedziane i zrobione, uznaliśmy, że ominięcie całego problemu poprzez zapewnienie bardzo małego zestawu podstawowych interfejsów, które mogą wyrzucić wyjątek w czasie wykonywania, to kompromis w zakresie inżynierii dźwięku.

Kiedy metody w API Collections są udokumentowane jako „operacje opcjonalne”, nie oznacza to, że możesz po prostu pozostawić implementację metody w implementacji, ani nie oznacza to, że możesz użyć pustej treści metody (po pierwsze, wiele z muszą zwrócić wynik). Oznacza to raczej, że prawidłowym wyborem implementacji (takim, który nadal jest zgodny z umową) jest wyrzucenie pliku UnsupportedOperationException.

Zauważ, że ponieważ UnsupportedOperationExceptionjest a RuntimeException, możesz go wyrzucić z dowolnej implementacji metody, jeśli chodzi o kompilator. Na przykład możesz wyrzucić to z implementacji Collection.size(). Jednak taka realizacja naruszyłaby umowę, ponieważ dokumentacja Collection.size()nie mówi, że jest to dozwolone.

Na marginesie: Podejście używane przez API Collections w Javie jest nieco kontrowersyjne (prawdopodobnie jednak mniej niż teraz, gdy zostało wprowadzone po raz pierwszy). W idealnym świecie interfejsy nie miałyby opcjonalnych operacji, a zamiast tego byłyby używane precyzyjne interfejsy. Problem polega na tym, że Java nie obsługuje ani wywnioskowanych typów strukturalnych, ani typów przecięcia, dlatego też próba robienia rzeczy we „właściwy sposób” kończy się w przypadku kolekcji wyjątkowo nieporęczną pracą.

Laurence Gonsalves
źródło
30
+1 dla There are no exceptions to this rule. Zastanawiasz się, dlaczego ta odpowiedź nie jest oznaczona jako zaakceptowana. Inni są dobrzy, ale dałeś więcej niż wystarczająco.
xyz,
9
„Język Java wymaga, aby każda metoda interfejsu była implementowana przez każdą implementację tego interfejsu. Kropka. Nie ma wyjątków od tej reguły”. Z wyjątkiem ... kiedy są. :-) Interfejsy Java 8 mogą określać domyślną implementację metody, więc w Javie 8 ... NIE jest prawdą, że każda metoda w interfejsie musi być ZAIMPLEMENTOWANA PRZEZ każdą implementację interfejsu, przynajmniej nie w tym sensie, że musisz zakoduj implementację w klasie conrete.
DaBlick
1
@DaBlick Kiedy powiedziałem „jest implementowany przez każdą implementację”, nie miałem na myśli, że ta implementacja metody musi znajdować się w źródle klasy implementującej. Jeszcze przed Java 8 można dziedziczyć implementację metody interfejsu, nawet z klasy, która nie implementuje wspomnianego interfejsu. np .: utwórz, Fooktóry nie jest implementowany Runnablemetodą publiczną void run(). Teraz utworzyć klasę Bar, że extends Fooi implements Runnablebez overiding run. Nadal implementuje metodę, choć pośrednio. Podobnie domyślna implementacja metody jest nadal implementacją.
Laurence Gonsalves,
Przeprosiny. Nie starałem się być pedantycznie krytyczny, ale zwracać uwagę na funkcję Java 8, która może być odpowiednia dla oryginalnego postu. W Javie 8 masz teraz możliwość posiadania implementacji, które nie są zakodowane w ŻADNEJ superklasie ani podklasie. To (IMHO) otwiera nowy świat wzorców projektowych, w tym niektóre, które mogą być odpowiednie w przypadkach, w których zakaz wielokrotnego dziedziczenia mógł stanowić pewne wyzwanie. Myślę, że zaowocuje to nowym zestawem bardzo przydatnych wzorców projektowych. \
DaBlick
3
@AndrewS, ponieważ w Javie 8 removepodano domyślną implementację. Jeśli tego nie zaimplementujesz, Twoja klasa otrzyma domyślną implementację. Pozostałe dwie metody, o których wspomniałeś, nie mają domyślnych implementacji.
Laurence Gonsalves
27

Aby skompilować implementującą (nieabstrakcyjną) klasę dla interfejsu - należy zaimplementować wszystkie metody.

Jeśli jednak pomyślimy o metodzie, której implementacja jest prostym rzutem wyjątku, jako o `` niezaimplementowanej '' metodzie (jak niektóre metody wCollection interfejsie), to Collectioninterfejs jest w tym przypadku wyjątkiem, a nie zwykłym przypadkiem. Zwykle klasa implementująca powinna (i będzie) implementowała wszystkie metody.

„Opcjonalne” w kolekcji oznacza, że ​​klasa implementująca nie musi jej „implementować” (zgodnie z powyższą terminologią) i po prostu ją wyrzuci NotSupportedException.

Dobry przykład- add() metoda niezmiennych kolekcji - beton po prostu zaimplementuje metodę, która nie robi nic poza rzucaniemNotSupportedException

W takim przypadku Collectionma to na celu zapobieganie bałaganiarskim drzewom dziedziczenia, które spowodują, że programiści będą nieszczęśliwi - ale dla większości przypadków ten paradygmat nie jest zalecany i należy go unikać, jeśli to możliwe.


Aktualizacja:

Od wersji java 8 metoda domyślna .

Oznacza to, że interfejs może definiować metodę - w tym jej implementację.
Zostało to dodane, aby umożliwić dodawanie funkcjonalności do interfejsów, jednocześnie wspierając kompatybilność wsteczną dla fragmentów kodu, które nie wymagają nowej funkcjonalności.

Zauważ, że metoda jest nadal implementowana przez wszystkie klasy, które ją deklarują, ale używają definicji interfejsu.

dobrze
źródło
Zamiast „nie zepsuć”, myślę, że chodzi bardziej o „tak właśnie jest”.
@pst: Uważam , że to, co myśleli projektanci, wdrażając go w pierwszej kolejności, ale nie mam sposobu, aby to wiedzieć na pewno. Myślę, że każde inne podejście spowodowałoby po prostu bałagan, ale znowu - może być błędne. Chodzi mi o to, że tutaj próbowałem pokazać: ten przykład jest wyjątkiem, a nie zwykłym - i chociaż czasami może się przydać - w ogólnym przypadku - należy go unikać, jeśli to możliwe.
rano
12
„nie musi tego implementować (prawdopodobnie stworzy metodę, która rzuca ...)”. To jest implementacja metody.
Markiz Lorne
1
Ponieważ jest to niestety akceptowana odpowiedź, proponuję ją przepisać. „ Zwykle klasa implementująca powinna (i będzie) implementować wszystkie metody” jest myląca, jak już wskazano w EJP .
Alberto
2
„Opcjonalne” w kolekcji oznacza, że ​​klasa implementująca nie musi jej implementować. ”- to jest po prostu fałsz. Przez„ nie musi implementować ”masz na myśli coś innego.
djechlin
19

Interfejs w Javie po prostu deklaruje kontrakt na implementację klas. Wszystkie metody w tym interfejsie muszą zostać zaimplementowane, ale klasy implementujące mogą pozostawić je niezaimplementowane, a mianowicie puste. Jako wymyślony przykład,

interface Foo {
  void doSomething();
  void doSomethingElse();
}

class MyClass implements Foo {
  public void doSomething() {
     /* All of my code goes here */
  }

  public void doSomethingElse() {
    // I leave this unimplemented
  }
}

Teraz pozostawiłem doSomethingElse()niezaimplementowany, pozostawiając go swobodnym do implementacji dla moich podklas. To jest opcjonalne.

class SubClass extends MyClass {
    @Override
    public void doSomethingElse() {
      // Here's my implementation. 
    }
}

Jeśli jednak mówisz o interfejsach kolekcji, jak powiedzieli inni, są one wyjątkiem. Jeśli pewne metody pozostaną niezaimplementowane i wywołasz je, mogą generować UnsupportedOperationExceptionwyjątki.

SRI
źródło
Mógłbym cię pocałować przyjacielu.
Mikro
16

Opcjonalne metody w interfejsie Collection oznaczają, że implementacja metody może zgłosić wyjątek, ale i tak musi zostać zaimplementowana. Jak określono w dokumentach :

Niektóre implementacje kolekcji mają ograniczenia dotyczące elementów, które mogą zawierać. Na przykład niektóre implementacje zabraniają pustych elementów, a niektóre mają ograniczenia dotyczące typów ich elementów. Próba dodania niekwalifikującego się elementu zgłasza niesprawdzony wyjątek, zwykle NullPointerException lub ClassCastException. Próba wysłania zapytania o obecność niekwalifikującego się elementu może zgłosić wyjątek lub po prostu zwrócić fałsz; niektóre implementacje będą wykazywać pierwsze zachowanie, a niektóre będą wykazywać drugie. Bardziej ogólnie, próba wykonania operacji na niekwalifikującym się elemencie, której zakończenie nie spowodowałoby wstawienia niekwalifikowalnego elementu do kolekcji, może zgłosić wyjątek lub może się powieść, w zależności od implementacji. Takie wyjątki są oznaczone jako „opcjonalne”

MByD
źródło
Nigdy tak naprawdę nie rozumiałem, co javadocs oznacza opcjonalne. Myślę, że mieli na myśli to, co powiedziałeś. Jednak większość metod jest opcjonalna według tego standardu new Runnable ( ) { @ Override public void run ( ) { throw new UnsupportedOperationException ( ) ; } }:;
emory
Wydaje się, że nie dotyczy to metod opcjonalnych , ale raczej, na przykład, add((T)null)może być ważne w jednym przypadku, ale nie w innym. Oznacza to, że mówi o opcjonalnych wyjątkach / zachowaniu i argumentach ("ograniczenia dotyczące elementów" ... "niekwalifikowalny element" ... "wyjątki oznaczone jako opcjonalne") i nie dotyczy metod opcjonalnych .
9

Aby kod mógł się skompilować, muszą zostać zaimplementowane wszystkie metody (poza tymi z defaultimplementacjami w Javie 8+), ale implementacja nie musi robić nic użytecznego funkcjonalnie. W szczególności:

  • Może być puste (metoda pusta).
  • Może po prostu rzucić UnsupportedOperationException(lub podobny)

To drugie podejście jest często stosowane w klasach kolekcji - wszystkie metody są nadal zaimplementowane, ale niektóre mogą zgłosić wyjątek, jeśli zostaną wywołane w czasie wykonywania.

Michael Berry
źródło
5

W rzeczywistości inspiruje mnie SurfaceView.Callback2. Myślę, że to oficjalny sposób

public class Foo {
    public interface Callback {
        public void requiredMethod1();
        public void requiredMethod2();
    }

    public interface CallbackExtended extends Callback {
        public void optionalMethod1();
        public void optionalMethod2();
    }

    private Callback mCallback;
}

Jeśli Twoja klasa nie musi implementować metod opcjonalnych, po prostu „implementuje wywołanie zwrotne”. Jeśli Twoja klasa wymaga implementacji metod opcjonalnych, po prostu „implementuje CallbackExtended”.

Przepraszam za gówno angielski.

Wonson
źródło
5

W Javie 8 i późniejszych, odpowiedź na to pytanie jest nadal aktualna, ale teraz jest bardziej zniuansowana.

Po pierwsze, te stwierdzenia z zaakceptowanej odpowiedzi pozostają poprawne:

  • interfejsy mają na celu określenie ich niejawnych zachowań w umowie (zestawienie zasad zachowania, które muszą spełniać klasy implementujące, aby zostały uznane za prawidłowe)
  • istnieje rozróżnienie między umową (zasadami) a wdrożeniem (programowe kodowanie zasad)
  • metody określone w interfejsie MUSZĄ być ZAWSZE implementowane (w pewnym momencie)

A więc jakie są nowe niuanse w Javie 8? Mówiąc o „metodach opcjonalnych”, można zastosować dowolne z poniższych:

1. Metoda, której wdrożenie jest umownie opcjonalne

„Trzecie stwierdzenie” mówi, że abstrakcyjne metody interfejsu muszą być zawsze implementowane i tak jest w Javie 8+. Jednak, podobnie jak w Java Collections Framework, niektóre abstrakcyjne metody interfejsu można opisać jako „opcjonalne” w kontrakcie.

W takim przypadku autor implementujący interfejs może zrezygnować z implementacji metody. Kompilator będzie jednak nalegał na implementację, więc autor używa tego kodu dla dowolnych metod opcjonalnych, które nie są potrzebne w danej klasie implementacji:

public SomeReturnType optionalInterfaceMethodA(...) {
    throw new UnsupportedOperationException();
}

W Javie 7 i wcześniejszych była to tak naprawdę jedyna „metoda opcjonalna”, która istniała, tj. Metoda, która, jeśli nie została zaimplementowana, zgłosiła wyjątek UnsupportedOperationException. To zachowanie jest koniecznie określone w kontrakcie interfejsu (np. Opcjonalne metody interfejsu Java Collections Framework).

2. Metoda domyślna, której ponowna implementacja jest opcjonalna

Java 8 wprowadziła koncepcję metod domyślnych . Są to metody, których implementacja może być i jest zapewniana przez samą definicję interfejsu. Generalnie możliwe jest udostępnienie metod domyślnych tylko wtedy, gdy treść metody może być napisana przy użyciu innych metod interfejsu (tj. „Prymitywów”) i kiedythis może oznaczać „ten obiekt, którego klasa zaimplementowała ten interfejs”.

Metoda domyślna musi spełniać kontrakt interfejsu (tak jak każda inna implementacja metody interfejsu). Dlatego określenie implementacji metody interfejsu w klasie implementującej jest w gestii autora (o ile zachowanie jest zgodne z jego przeznaczeniem).

W tym nowym środowisku Java Collections Framework można przepisać jako:

public interface List<E> {
    :
    :
    default public boolean add(E element) {
        throw new UnsupportedOperationException();
    }
    :
    :
}

W ten sposób metoda „opcjonalna” add()ma domyślne zachowanie polegające na zgłaszaniu wyjątku UnsupportedOperationException, jeśli klasa implementująca nie zapewnia własnego nowego zachowania, co jest dokładnie tym, co chciałbyś, aby się wydarzyło i jest zgodne z umową dotyczącą List. Jeśli autor pisze klasę, która nie pozwala na dodawanie nowych elementów do implementacji List, implementacjaadd() jest opcjonalna, ponieważ domyślne zachowanie jest dokładnie tym, co jest potrzebne.

W tym przypadku „trzecia instrukcja” powyżej nadal jest prawdziwa, ponieważ metoda została zaimplementowana w samym interfejsie.

3. Metoda zwracająca Optionalwynik

Ostatnim nowym rodzajem metody opcjonalnej jest po prostu metoda, która zwraca Optional. Ta Optionalklasa zapewnia zdecydowanie bardziej zorientowany obiektowo sposób postępowanianull wynikami.

W płynnym stylu programowania, takim jak typowy typowy podczas kodowania za pomocą nowego interfejsu API strumieniowania w języku Java, wynik zerowy w dowolnym momencie powoduje awarię programu z wyjątkiem NullPointerException. PlikOptionalKlasa zapewnia mechanizm zwracania wyników zerowych do kodu klienta w sposób, który umożliwia płynny styl bez powodowania kod klienta do katastrofy.

scottb
źródło
4

Jeśli przejdziemy przez kod AbstractCollection.java w grepCode, który jest klasą nadrzędną dla wszystkich implementacji kolekcji, pomoże nam to zrozumieć znaczenie metod opcjonalnych. Oto kod metody add (e) w klasie AbstractCollection. metoda add (e) jest opcjonalna zgodnie z interfejsem kolekcji

public boolean  add(E e) {

        throw new UnsupportedOperationException();
    } 

Metoda opcjonalna oznacza, że ​​jest już zaimplementowana w klasach nadrzędnych i zgłasza UnsupportedOperationException przy wywołaniu. Jeśli chcemy, aby nasza kolekcja była modyfikowalna, powinniśmy przesłonić opcjonalne metody w interfejsie kolekcji.

IsAs
źródło
4

Cóż, ten temat został skierowany do ... tak ... ale myślę, że brakuje jednej odpowiedzi. Mówię o „domyślnych metodach” interfejsów. Na przykład, wyobraźmy sobie, że masz klasę do zamykania czegokolwiek (np. Destruktora lub czegoś podobnego). Powiedzmy, że powinno mieć 3 metody. Nazwijmy je „doFirst ()”, „doLast ()” i „onClose ()”.

Więc mówimy, że chcemy, aby każdy obiekt tego typu przynajmniej realizował "onClose ()", ale pozostałe są opcjonalne.

Możesz to sobie uświadomić, używając "domyślnych metod" interfejsów. Wiem, że przez większość czasu zanegowałoby to przyczynę interfejsu, ale jeśli projektujesz framework, może to być przydatne.

Więc jeśli chcesz to zrealizować w ten sposób, wyglądałoby to następująco

public interface Closer {
    default void doFirst() {
        System.out.print("first ... ");
    }
    void onClose();
    default void doLast() {
        System.out.println("and finally!");
    }
}

Co by się teraz stało, gdybyś na przykład zaimplementował go w klasie o nazwie „Test”, kompilator byłby w porządku z następującymi elementami:

public class TestCloser implements Closer {
    @Override
    public void onClose() {
        System.out.print("closing ... ");
    }
}

z wyjściem:

first ... closing ... and finally!

lub

public class TestCloser implements Closer {
    @Override
    public void onClose() {
        System.out.print("closing ... ");
    }

    @Override
    public void doLast() {
        System.out.println("done!");
    }
}

z wyjściem:

first ... closing ... done!

Możliwe są wszystkie kombinacje. Wszystko, co ma wartość „domyślną”, może zostać zaimplementowane, ale nie może, jednak wszystko bez musi zostać wdrożone.

Mam nadzieję, że nie jest całkowicie błędne, że teraz odpowiadam.

Życzę wszystkim miłego dnia!

[edit1]: Uwaga: to działa tylko w Javie 8.

Thorben Kuck
źródło
Tak, przepraszam, zapomniałem o tym wspomnieć ... Powinien być teraz zredagowany.
Thorben Kuck
1

Szukałem sposobu na zaimplementowanie interfejsu wywołania zwrotnego, więc zaimplementowanie metod opcjonalnych było konieczne, ponieważ nie chciałem implementować każdej metody dla każdego połączenia zwrotnego.

Zamiast więc korzystać z interfejsu, użyłem klasy z pustą implementacją, taką jak:

public class MyCallBack{
    public void didResponseCameBack(String response){}
}

I możesz ustawić zmienną członkowską CallBack w ten sposób:

c.setCallBack(new MyCallBack() {
    public void didResponseCameBack(String response) {
        //your implementation here
    }
});

to nazwij to tak.

if(mMyCallBack != null) {
    mMyCallBack.didResponseCameBack(response);
}

W ten sposób nie musisz martwić się o implementację wszystkich metod na wywołanie zwrotne, a jedynie nadpisać te, których potrzebujesz.

green0range
źródło
0

Chociaż nie odpowiada to na pytanie OP, warto zauważyć, że od wersji Java 8 dodawanie domyślnych metod do interfejsów jest w rzeczywistości możliwe . Słowo defaultkluczowe umieszczone w sygnaturze metody interfejsu spowoduje, że klasa będzie miała opcję nadpisania metody, ale nie będzie tego wymagać.

Troy Stopera
źródło
0

Samouczek dotyczący kolekcji Java firmy Oracle:

Aby utrzymać liczbę podstawowych interfejsów kolekcji, którymi można zarządzać, platforma Java nie zapewnia oddzielnych interfejsów dla każdego wariantu każdego typu kolekcji. (Takie warianty mogą obejmować niezmienne, o stałym rozmiarze i tylko do dołączania). Zamiast tego operacje modyfikacji w każdym interfejsie są oznaczone jako opcjonalne - dana implementacja może nie obsługiwać wszystkich operacji. Jeśli zostanie wywołana nieobsługiwana operacja, kolekcja zgłosi UnsupportedOperationException . Implementacje są odpowiedzialne za dokumentowanie, które z opcjonalnych operacji obsługują. Wszystkie implementacje ogólnego przeznaczenia platformy Java obsługują wszystkie opcjonalne operacje.

Trent Steele
źródło