28 Stimmen

Was ist der Zweck von Platzhaltern und wie unterscheiden sie sich von Generika?

Bis vor ein paar Tagen hatte ich noch nie etwas von Wildcars gehört, und nachdem ich das Java-Buch meines Lehrers gelesen habe, bin ich mir immer noch nicht sicher, wozu es gut ist und warum ich es verwenden sollte.

Nehmen wir an, ich habe eine Superklasse Animal und einige Unterklassen wie Dog , Cat , Parrot usw. ... Jetzt muss ich eine Liste von Tieren haben, mein erster Gedanke wäre etwas wie:

List<Animal> listAnimals

Stattdessen empfehlen meine Kollegen etwas wie:

List<? extends Animal> listAnimals

Warum sollte ich Wildcards anstelle von einfachen Generika verwenden?

Angenommen, ich benötige eine get/set-Methode, sollte ich erstere oder letztere verwenden? Inwiefern sind sie so unterschiedlich?

27voto

Alexander Pogrebnyak Punkte 43705

Die Platzhalter sind bei der Deklaration lokaler Variablen nicht sehr sinnvoll, aber bei der Deklaration eines Parameters für eine Methode sind sie sehr wichtig.

Stellen Sie sich vor, Sie haben eine Methode:

int countLegs ( List< ? extends Animal > animals )
{
   int retVal = 0;
   for ( Animal cur : animals )
   {
      retVal += cur.countLegs( );
   }

   return retVal;
}

Mit dieser Signatur können Sie dies tun:

List<Dog> dogs = ...;
countLegs( dogs );

List<Cat> cats = ...;
countLegs( cats );

List<Animal> zoo = ...;
countLegs( zoo );

Wenn Sie jedoch erklären, dass Sie countLegs wie diese:

int countLegs ( List< Animal > animals )

Im vorigen Beispiel wurde dann nur countLegs( zoo ) hätte kompiliert werden können, da nur dieser Aufruf einen korrekten Typ hat.

25voto

polygenelubricants Punkte 362173

Java-Generika sind invariant.

Angenommen, wir haben B extends A :

  • B ist ein Subtyp von A
  • eine instanceof B ist auch ein instanceof A

Da Java-Arrays kovariant sind:

  • B[] ist ein Subtyp von A[]
  • eine instanceof B[] ist auch ein instanceof A[]

Java-Generika sind jedoch invariant:

  • List<B> ist NICHT ein Subtyp von List<A>
  • a instanceof List<B> ist NICHT ein instanceof List<A> .

Wildcards werden verwendet, um die Flexibilität zu erhöhen und gleichzeitig die Typsicherheit zu gewährleisten.

  • a List<B> ist eine List<? extends A>

Referenzen

Verwandte Fragen

10voto

froadie Punkte 75709

Der Unterschied zwischen Ihren beiden Beispielen besteht einfach darin, dass das erste eine Liste allgemeiner Tiere ist - Sie können ihr also jede Art von Tier und jede Instanz einer Unterklasse des Typs Tier hinzufügen. (z.B. kann sie einige Hunde, einige Katzen, einige Stachelschweine enthalten...) Während das zweite - List <? extends Animal> - wird eine Liste von einen bestimmten Subtyp der Klasse Tier. Es kann ein beliebiges sein (dies wird jedes Mal zur Laufzeit festgelegt), aber nur eines. Es wird entweder eine Liste von Hunden sein, または eine Liste von Katzen, または eine Liste von Schildkröten... usw.

2voto

COME FROM Punkte 2447

Sie können Hunde und Katzen in einem List<Animal> . Hier werden keine Platzhalter benötigt.

Angenommen, Sie haben eine Methode, die eine Liste von Tieren aufnimmt:

void foo(List<Animal> animals) {
    ...
}

Jetzt können Sie der Methode keine Liste von Hunden übergeben - sie nimmt nur ein Argument vom Typ List<Animal> . Sie benötigen einen Platzhalter, damit die Methode alle Arten von Listen von Tieren akzeptiert: List<Animal> , List<Dog> , List<Cat> , ...

void foo(List<? extends Animal> animals) {
    ...
}

Siehe

http://java.sun.com/docs/books/tutorial/extra/generics/wildcards.html

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X