Frage an java, interface, methods – Optionale Methoden in der Java-Oberfläche

101

Wenn Sie eine Schnittstelle in Java implementieren, müssen meines Erachtens die in dieser Schnittstelle angegebenen Methoden von den Unterklassen verwendet werden, die diese Schnittstelle implementieren.

Ich habe festgestellt, dass es in einigen Interfaces wie dem Collection-Interface Methoden gibt, die als optional kommentiert sind, aber was genau bedeutet das? Es hat mich ein wenig geworfen, als ich dachte, dass alle in der Schnittstelle angegebenen Methoden erforderlich wären?

Auf welche Methoden beziehen Sie sich? Ich kann es im JavaDoc oder im Quellcode nicht finden dcpomero

Deine Antwort

12   die antwort
4

Schnittstellen sollen ihr implizites Verhalten in einem Vertrag angeben (eine Erklärung zu Verhaltensregeln, die implementierende Klassen befolgen müssen, um als gültig angesehen zu werden).

Es wird zwischen dem Vertrag (Regeln) und der Umsetzung (programmatische Kodierung der Regeln) unterschieden.Methoden, die in der Schnittstelle angegeben sind, MÜSSEN IMMER implementiert sein (irgendwann)Welche Nuance ist neu in Java 8? Wenn ich davon spreche

Optionale Methoden Eine der folgenden Optionen ist jetzt passend:1. Eine Methode, deren Implementierung vertraglich optional ist

Die "dritte Anweisung" besagt, dass abstrakte Schnittstellenmethoden immer implementiert werden müssen, und dies gilt auch für Java 8+. Wie im Java Collections Framework ist es jedoch möglich, einige abstrakte Schnittstellenmethoden im Vertrag als "optional" zu bezeichnen.

In diesem Fall kann der Autor, der die Schnittstelle implementiert, entscheiden, die Methode nicht zu implementieren. Der Compiler besteht jedoch auf einer Implementierung. Daher verwendet der Autor diesen Code für optionale Methoden, die in der jeweiligen Implementierungsklasse nicht benötigt werden:

In Java 7 und früheren Versionen war dies tatsächlich die einzige Art von "optionaler Methode", die es gab, d. H. Eine Methode, die, falls sie nicht implementiert war, eine "UnsupportedOperationException" auslöste. Dieses Verhalten wird notwendigerweise durch den Schnittstellenvertrag festgelegt (z. B. die optionalen Schnittstellenmethoden des Java Collections Framework).

<code>public SomeReturnType optionalInterfaceMethodA(...) {
    throw new UnsupportedOperationException();
}
</code>

2. Eine Standardmethode, deren Neuimplementierung optional ist

Java 8 führte das Konzept von ein

Standardmethoden. Dies sind Methoden, deren Implementierung von der Schnittstellendefinition selbst bereitgestellt werden kann und wird. Es ist im Allgemeinen nur möglich, Standardmethoden bereitzustellen, wenn der Methodenkörper unter Verwendung anderer Schnittstellenmethoden (d. H. Der "Grundelemente") geschrieben werden kann und wann kann bedeuten "dieses Objekt, dessen Klasse diese Schnittstelle implementiert hat."thisEine Standardmethode muss den Vertrag der Schnittstelle erfüllen (genau wie jede andere Implementierung einer Schnittstellenmethode). Die Angabe einer Implementierung der Schnittstellenmethode in einer implementierenden Klasse liegt daher im Ermessen des Autors (sofern das Verhalten für seinen Zweck geeignet ist).

In dieser neuen Umgebung das Java Collections Framework

könnte sein umgeschrieben als:Auf diese Weise die "optionale" Methode

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

 hat das Standardverhalten, eine UnsupportedOperationException auszulösen, wenn die implementierende Klasse kein eigenes neues Verhalten bereitstellt. Dies ist genau das, was geschehen soll und das mit dem Vertrag für List kompatibel ist. Wenn ein Autor eine Klasse schreibt, die das Hinzufügen neuer Elemente zu einer List-Implementierung nicht zulässt, wird die Implementierung vonadd() ist optional, da das Standardverhalten genau das ist, was benötigt wird.add()In diesem Fall gilt die obige "dritte Anweisung" weiterhin, da die Methode in der Schnittstelle selbst implementiert wurde.

3. Eine Methode, die ein zurückgibt

 ErgebnisOptionalDie letzte neue Art der optionalen Methode ist einfach eine Methode, die ein zurückgibt

. DasOptional class bietet einen deutlich objektorientierteren UmgangOptional Ergebnisse.nullBei einem fließenden Programmierstil, wie er häufig beim Codieren mit der neuen Java Streams-API auftritt, führt ein Null-Ergebnis zu jedem Zeitpunkt dazu, dass das Programm mit einer NullPointerException abstürzt. Das

 class bietet einen Mechanismus zum Zurückgeben von NULL-Ergebnissen an den Clientcode auf eine Weise, die den fließenden Stil ermöglicht, ohne dass der Clientcode abstürzt.OptionalTatsächlich bin ich von SurfaceView.Callback2 inspiriert. Ich denke, das ist der offizielle Weg

3

implementiert Callback". Wenn Ihre Klasse optionale Methoden implementieren muss, "implementiert CallbackExtended".

<code>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;
}
</code>

Entschuldigung für die Scheiße Englisch.

Nun, dieses Thema wurde angesprochen ... ja ... aber denke, eine Antwort fehlt. Ich spreche über die "Standardmethoden" von Schnittstellen. Stellen wir uns zum Beispiel vor, Sie haben eine Klasse, mit der Sie alles schließen können (z. B. einen Destruktor oder etwas anderes). Sagen wir, es sollte 3 Methoden haben. Nennen wir sie "doFirst ()", "doLast ()" und "onClose ()".

17

Muss implementiert werden, aber es steht den implementierenden Klassen frei, sie nicht zu implementieren, d. h. leer zu lassen. Als konstruiertes BeispielJetzt bin ich gegangen

<code>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
  }
}
</code>

 unimplementiert, so dass meine Unterklassen sie implementieren können. Das ist fakultativ.doSomethingElse()Wenn Sie jedoch über Collection-Schnittstellen sprechen, wie andere bereits gesagt haben, sind sie eine Ausnahme. Wenn bestimmte Methoden nicht implementiert werden und Sie diese aufrufen, können sie ausgelöst werden

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

 Ausnahmen.UnsupportedOperationExceptionIch könnte dich küssen, mein Freund.

Die optionalen Methoden in der Collection-Schnittstelle bedeuten, dass die Implementierung der Methode eine Ausnahme auslösen darf, diese aber trotzdem implementiert werden muss. Wie angegeben Micro
3

onClose ()" realisiert, die anderen sind jedoch optional.

Sie können dies mit den "Standardmethoden" der Schnittstellen realisieren. Ich weiß, dies würde die meiste Zeit den Grund einer Schnittstelle negieren, aber wenn Sie ein Framework entwerfen, kann dies nützlich sein.

Wenn Sie es also auf diese Weise realisieren möchten, sieht es folgendermaßen aus

Was nun passieren würde, wenn Sie es zum Beispiel in einer Klasse namens "Test" implementieren würden, wäre der Compiler in Ordnung mit dem Folgenden:

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

mit der Ausgabe:

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

oder

<code>first ... closing ... and finally!
</code>

mit der Ausgabe:

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

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

Alle Kombinationen sind möglich. Alles mit "default" kann implementiert werden, muss aber nicht, alles ohne muss implementiert werden.

<code>first ... closing ... done!
</code>

Hoffe es ist nicht ganz falsch, dass ich jetzt antworte.

Einen schönen Tag euch allen!

[edit1]: Bitte beachten Sie: Dies funktioniert nur in Java 8.

Dies funktioniert nur mit Java 8, oder? *

danke für die hilfe thorben Thorben Kuck
Obwohl es die Frage des OP nicht beantwortet, ist es erwähnenswert, dass ab Java 8 Standardmethoden zu Schnittstellen hinzugefügt werden AndroidLover
Ja, sorry, ich habe vergessen, dies zu erwähnen ... Sollte jetzt bearbeitet werden. AndroidLover
0

habe ich eine Klasse mit einer leeren Implementierung verwendet, wie zum Beispiel:

Und Sie können Mitglied Variable CallBack wie folgt einstellen,

<code>public class MyCallBack{
    public void didResponseCameBack(String response){}
}
</code>

dann nenne es so.

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

Auf diese Weise müssen Sie sich nicht um die Implementierung aller Methoden pro Rückruf kümmern, sondern müssen nur die von Ihnen benötigten überschreiben.

<code>if(mMyCallBack != null) {
    mMyCallBack.didResponseCameBack(response);
}
</code>

Oracle Java Collections Tutorial:

205

Die Java-Sprache erfordert, dass jede Methode in einer Schnittstelle von jeder Implementierung dieser Schnittstelle implementiert wird. Zeitraum.Es gibt keine Ausnahmen zu dieser Regel. Zu sagen, dass "Sammlungen eine Ausnahme sind", deutet auf ein sehr verschwommenes Verständnis dessen hin, was hier wirklich vor sich geht.

Es ist wichtig zu wissen, dass es zwei Ebenen für die Anpassung an eine Schnittstelle gibt:

Was die Java-Sprache überprüfen kann. Das läuft so ziemlich nur darauf hinaus, ob es da istetwas Implementierung für jede der Methoden?

Den Vertrag tatsächlich erfüllen. Funktioniert die Implementierung also so, wie es die Dokumentation in der Benutzeroberfläche vorschreibt?

Gut geschriebene Schnittstellen enthalten eine Dokumentation, in der genau erklärt wird, was von den Implementierungen erwartet wird. Ihr Compiler kann dies nicht für Sie überprüfen. Sie müssen die Dokumente lesen und tun, was sie sagen. Wenn Sie nicht tun, was der Vertrag sagt, dann haben Sie eine Implementierung der Schnittstelle bis zuCompiler ist besorgt, aber es wird eine fehlerhafte / ungültige Implementierung sein.

Als Joshua Bloch die Collections-API entwarf, entschied er, dass er anstatt sehr feinkörniger Schnittstellen zur Unterscheidung verschiedener Varianten von Sammlungen (z. B. lesbar, beschreibbar, Direktzugriff usw.) in erster Linie nur sehr grobe Schnittstellen verwenden würdeCollection, List, Set undMapund dokumentieren Sie dann bestimmte Vorgänge als "optional". Dies sollte die kombinatorische Explosion vermeiden, die sich aus feinkörnigen Grenzflächen ergeben würde. Von demHäufig gestellte Fragen zum Java Collections API-Design:

Angenommen, Sie möchten der Hierarchie den Begriff der Modifizierbarkeit hinzufügen, um das Problem im Detail zu veranschaulichen. Sie benötigen vier neue Schnittstellen: ModifiableCollection, ModifiableSet, ModifiableList und ModifiableMap. Was früher eine einfache Hierarchie war, ist jetzt eine chaotische Heterarchie. Außerdem benötigen Sie eine neue Iterator-Schnittstelle für die Verwendung mit nicht modifizierbaren Sammlungen, die den Entfernungsvorgang nicht enthält. Können Sie UnsupportedOperationException jetzt abschaffen? Leider nicht.

Betrachten Sie Arrays. Sie implementieren die meisten Listenoperationen, entfernen und fügen sie jedoch nicht hinzu. Es handelt sich um Listen mit fester Größe. Wenn Sie diesen Begriff in der Hierarchie erfassen möchten, müssen Sie zwei neue Schnittstellen hinzufügen: VariableSizeList und VariableSizeMap. Sie müssen VariableSizeCollection und VariableSizeSet ​​nicht hinzufügen, da sie mit ModifiableCollection und ModifiableSet identisch sind. Sie können sie jedoch aus Gründen der Konsistenz trotzdem hinzufügen. Außerdem benötigen Sie eine neue ListIterator-Variante, die das Hinzufügen und Entfernen von Elementen nicht unterstützt. Jetzt haben wir bis zu zehn oder zwölf Schnittstellen sowie zwei neue Iterator-Schnittstellen anstelle unserer ursprünglichen vier. Sind wir fertig? Nein.

Berücksichtigen Sie Protokolle (z. B. Fehlerprotokolle, Überwachungsprotokolle und Journale für wiederherstellbare Datenobjekte). Hierbei handelt es sich um natürliche Anhängefolgen, die alle Listenoperationen mit Ausnahme von Entfernen und Setzen (Ersetzen) unterstützen. Sie erfordern eine neue Kernschnittstelle und einen neuen Iterator.

Und was ist mit unveränderlichen Sammlungen im Gegensatz zu nicht veränderbaren? (d. h. Sammlungen, die vom Client nicht geändert werden können UND sich aus keinem anderen Grund ändern). Viele argumentieren, dass dies der wichtigste Unterschied von allen ist, da mehrere Threads gleichzeitig auf eine Sammlung zugreifen können, ohne dass eine Synchronisierung erforderlich ist. Um diese Unterstützung zur Typhierarchie hinzuzufügen, sind vier weitere Schnittstellen erforderlich.

Jetzt haben wir ungefähr zwanzig Schnittstellen und fünf Iteratoren, und es ist fast sicher, dass es in der Praxis immer noch Sammlungen gibt, die in keine der Schnittstellen passen. Beispielsweise handelt es sich bei den von Map zurückgegebenen Sammlungsansichten um reine Löschsammlungen. Es gibt auch Sammlungen, die bestimmte Elemente aufgrund ihres Werts ablehnen. Daher haben wir die Laufzeitausnahmen immer noch nicht beseitigt.

Letztendlich hielten wir es für einen soliden technischen Kompromiss, das ganze Problem zu umgehen, indem wir einen sehr kleinen Satz von Kernschnittstellen zur Verfügung stellten, die eine Laufzeitausnahme auslösen können.

Wenn Methoden in der Collections-API als "optionale Operationen" dokumentiert sind, bedeutet dies nicht, dass Sie die Methodenimplementierung einfach in der Implementierung auslassen oder einen leeren Methodenkörper verwenden können (zum einen viele) sie müssen ein Ergebnis zurückgeben). Es bedeutet vielmehr, dass eine gültige Implementierungsentscheidung (eine, die immer noch dem Vertrag entspricht) darin besteht, eine zu werfenUnsupportedOperationException.

Beachten Sie, dass weilUnsupportedOperationException ist einRuntimeException Sie können es aus jeder Methodenimplementierung werfen, soweit der Compiler betroffen ist. Sie könnten es beispielsweise aus einer Implementierung von werfenCollection.size(). Eine solche Implementierung würde jedoch den Vertrag als Dokumentation für verletzenCollection.size() sagt nicht, dass dies erlaubt ist.

Übrigens: Der von der Java-API Collections verwendete Ansatz ist etwas umstritten (wahrscheinlich jedoch weniger als zu Beginn der Einführung). In einer perfekten Welt würden Schnittstellennicht haben optionale Operationen, und feinkörnige Schnittstellen würden stattdessen verwendet. Das Problem ist, dass Java weder abgeleitete Strukturtypen noch Schnittstellentypen unterstützt, weshalb der Versuch, Dinge auf die "richtige Weise" zu tun, bei Sammlungen äußerst unhandlich wird.

@ Andrews weil in Java 8 Andrew S
Um eine implementierende (nicht abstrakte) Klasse für eine Schnittstelle zu kompilieren, müssen alle Methoden implementiert werden. Andrew S
Entschuldigung. Ich habe nicht versucht, pedantisch kritisch zu sein, um die Aufmerksamkeit auf eine Java 8-Funktion zu lenken, die für den ursprünglichen Beitrag relevant sein könnte. In Java 8 haben Sie jetzt die Möglichkeit, Implementierungen zu verwenden, die weder in einer Superklasse noch in einer Unterklasse codiert sind. Dies (IMHO) eröffnet eine neue Welt von Entwurfsmustern, einschließlich einiger, die in Fällen geeignet sein könnten, in denen das Verbot der Mehrfachvererbung einige Herausforderungen mit sich gebracht haben könnte. Ich denke, dies wird eine neue Reihe von äußerst nützlichen Designmustern hervorbringen. \ Warum beschwert sich der Compiler beim Implementieren der Iterator-Schnittstelle in meiner Klasse nicht über das Fehlen der remove () -Methode, sondern über die fehlenden next () - und hasNext () -Methoden? DaBlick
"Die Java-Sprache erfordert, dass jede Methode in einer Schnittstelle von jeder Implementierung dieser Schnittstelle implementiert wird. Periode. Es gibt keine Ausnahmen von dieser Regel." Außer ... wenn es welche gibt. :-) Java 8-Schnittstellen können eine Standardmethodenimplementierung angeben. In Java 8 ... ist es also NICHT wahr, dass jede Methode in einer Schnittstelle von jeder Implementierung der Schnittstelle IMPLEMENTIERT werden muss, zumindest nicht in dem Sinne, wie Sie es müssen Code die Implementierung in der Conrete-Klasse. DaBlick
4

AbstractCollection.java In grepCode, einer Vorgängerklasse für alle Auflistungsimplementierungen, können wir die Bedeutung optionaler Methoden besser verstehen. Hier ist der Code für die Methode add (e) in der Klasse AbstractCollection. add (e) Methode ist optional nachSammlung SchnittstelleOptionale Methode bedeutet, dass sie bereits in Vorfahrklassen implementiert ist und beim Aufruf eine UnsupportedOperationException auslöst. Wenn wir unsere Sammlung änderbar machen möchten, sollten wir die überschreiben

<code>public boolean  add(E e) {

        throw new UnsupportedOperationException();
    } 
</code>

wahlweise Methoden in der Sammlungsschnittstelle.In Java 8 und höher ist die Antwort auf diese Frage immer noch gültig, aber jetzt nuancierter.

9

  aber die Implementierung muss nichts funktionell Nützliches tun. Im Einzelnen ist es:defaultKann leer sein (eine leere Methode.)

Darf nur einen werfen (oder ähnliches)UnsupportedOperationExceptionDer letztgenannte Ansatz wird häufig in den Auflistungsklassen verwendet - alle Methoden sind noch implementiert, einige lösen jedoch möglicherweise eine Ausnahme aus, wenn sie zur Laufzeit aufgerufen werden.

Wenn wir den Code von

0

. Das Das in der Methodensignatur einer Schnittstelle platzierte Schlüsselwort führt dazu, dass eine Klasse die Option hat, die Methode zu überschreiben, dies jedoch nicht erforderlich ist.defaultIch suchte nach einer Möglichkeit, die Rückrufschnittstelle zu implementieren, sodass die Implementierung optionaler Methoden erforderlich war, da ich nicht jede Methode für jeden Rückruf implementieren wollte.

25

Wenn wir uns eine Methode vorstellen, deren Implementierung eine einfache Ausnahme darstellt, wird sie als 'nicht implementiert' geworfen (wie einige Methoden in der Schnittstelle), dann dieCollection Schnittstelle ist in diesem Fall die Ausnahme, nicht der Normalfall.CollectionMeistensDie Implementierung der Klasse sollte (und wird) alle Methoden implementieren.Das "optional" in der Auflistung bedeutet, dass die implementierende Klasse sie nicht 'implementieren' muss (gemäß der obigen Terminologie), und sie wirft nur

).NotSupportedExceptionEin gutes Beispiel-

 Methode für unveränderliche Sammlungen - der Beton wird nur eine Methode implementieren, die nichts anderes tut als zu werfenadd()Im Falle vonNotSupportedException

 es wird getan, um unordentliche Erbbäume zu verhindern, die Programmierer unglücklich machen - aber fürCollectiondie meisten In einigen Fällen wird dieses Paradigma nicht empfohlen und sollte nach Möglichkeit vermieden werden.Aktualisieren:

Ab Java 8, a

Standardmethode wurde vorgestellt.Das heißt, eine Schnittstelle kann eine Methode definieren - einschließlich ihrer Implementierung.

Dies wurde hinzugefügt, um das Hinzufügen von Funktionen zu Schnittstellen zu ermöglichen und gleichzeitig die Abwärtskompatibilität für Codeteile zu unterstützen, für die die neue Funktionalität nicht erforderlich ist.
Beachten Sie, dass die Methode immer noch von allen Klassen implementiert wird, die sie deklarieren, aber die Definition der Schnittstelle verwendet.

Anstatt "nicht durcheinander zu bringen", denke ich, ist es eher "so ist es eben".

ist Implementierung der Methode.Da dies leider die akzeptierte Antwort war, würde ich vorschlagen, es umzuschreiben. Das ' user207421
Eine Schnittstelle in Java deklariert lediglich den Vertrag für die Implementierung von Klassen. Alle Methoden in dieser Schnittstelle djechlin
glauben Das haben sich die Designer gedacht, als sie es implementiert haben, aber ich kann es nicht mit Sicherheit wissen. ichdenken Jeder andere Ansatz würde nur ein Chaos hervorrufen, könnte aber auch hier falsch sein. Der Punkt, den ich hier zeigen wollte, ist: Dieses Beispiel ist die Ausnahme, nicht die übliche - und obwohl es manchmal nützlich sein kann - für den allgemeinen Fall, sollte es nach Möglichkeit vermieden werden.msgstr "muss nicht implementiert werden (es wird wahrscheinlich nur eine Methode erstellt, die ... auslöst)". Das amit
MeistensDie Implementierung einer Klasse sollte (und wird) alle Methoden implementieren, da dies irreführend istEJP bereits darauf hingewiesen.Das "optional" in der Auflistung bedeutet, dass die implementierende Klasse es nicht implementieren muss. "- dies ist einfach falsch. Mit" muss nicht implementieren "meinen Sie etwas anderes. Alberto
@ PST: Ich user166390
16

Einige Auflistungsimplementierungen haben Einschränkungen hinsichtlich der Elemente, die sie enthalten können. Beispielsweise verbieten einige Implementierungen Nullelemente, und einige haben Einschränkungen hinsichtlich der Typen ihrer Elemente. Der Versuch, ein nicht auswählbares Element hinzuzufügen, löst eine ungeprüfte Ausnahme aus, normalerweise NullPointerException oder ClassCastException. Der Versuch, das Vorhandensein eines nicht auswählbaren Elements abzufragen, kann eine Ausnahme auslösen oder einfach false zurückgeben. Einige Implementierungen zeigen das erstere Verhalten, andere das letztere. Im Allgemeinen kann der Versuch einer Operation mit einem nicht berechtigten Element, dessen Abschluss nicht zum Einfügen eines nicht berechtigten Elements in die Auflistung führt, nach Wahl der Implementierung eine Ausnahme auslösen oder erfolgreich sein. Solche Ausnahmen sind in der Spezifikation für diese Schnittstelle als "optional" gekennzeichnet.:

Ich habe nie wirklich verstanden, was die Javadocs mit optional meinten. Ich glaube, sie meinten, wie du gesagt hast. Aber die meisten Methoden sind nach diesem Standard optional:

optionale Methodensondern dass zum Beispiel kann in einem fall aber gültig seinadd((T)null)nicht Ein weiterer. Das heißt, hier geht es um optionale Ausnahmen / Verhaltensweisen undfür Argumente ("Einschränkungen für Elemente" ... "nicht förderfähige Elemente" ... "als optional gekennzeichnete Ausnahmen") und wird nicht behandeltoptionale MethodenAlle Methoden müssen implementiert sein, damit der Code kompiliert werden kann (außer denen mit. user166390
Dies scheint nicht zuzutreffennew Runnable ( ) { @ Override public void run ( ) { throw new UnsupportedOperationException ( ) ; } }; emory

Verwandte Fragen