In Guave, warum ist nur "T" wo verwendet? Super T "wäre möglich?

8

Warum verwenden die Utility-Factory-Methoden häufig einen spezifischen generischen Parameter (wie T ) anstelle eines beschränkten Wildcard-Parameters (wie ? super T )?

Zum Beispiel die Signatur von Funktionen # forPredicate ist:

%Vor%

Warum nicht verwenden:

%Vor%

Was würde so etwas wie möglich machen?

%Vor%

Liegt das daran, dass Konsumenten von Function und Predicate die erforderlichen beschränkten Wildcard-Parameter haben müssen, um dies unnötig zu machen? Beispiel: Die generischen Grenzen für Iterables # find würde erlauben, dass Predicate<Number> auf einem Iterable<Integer> verwendet wird:

%Vor%

Gibt es andere Gründe?

    
matts 31.01.2013, 17:11
quelle

2 Antworten

6

Ja, es ist absolut richtig, dass wir erwarten, dass die Verbraucher die richtigen begrenzten Wildcard-Parameter haben, aber ein paar weitere Gründe fallen einem ein:

  • Im Allgemeinen erweitern wir die Arten von generischen Methoden nicht, bis wir einen bestimmten Grund dafür haben. Diese Politik hat sich mehrfach ausgezahlt.
  • Die Typinferenz von Java ist nicht immer dazu geeignet, automatischere Generika automatisch zu berechnen, sodass die Anzahl der Benutzer, die T explizit angeben müssen, durch die Beibehaltung der schmaleren Generika reduziert wird.
Louis Wasserman 31.01.2013, 17:50
quelle
2

Im find() Beispiel kann T immer eindeutig abgeleitet werden.

Im Beispiel forPredicate[1]() kann T auch eindeutig abgeleitet werden.

Im Beispiel forPredicate[2]() gibt es Ungewissheit, was T sein sollte. Wenn das Ergebnis der Methode einem Zieltyp zugeordnet ist, kann T aus dem Zieltyp ermittelt werden. Sonst ist es ein bisschen Kopf kratzen:

%Vor%

In Java5 / 6 sollte es nicht kompiliert werden. (Nun, ich habe es auf Java 6 getestet und es kompiliert, aber es ist wahrscheinlich ein Fehler, da Java 6 auch forPredicate(p).apply("str") kompiliert)

Java 7 hat sich ein wenig verbessert, und die neue Regel diktiert das T=Number . Es funktioniert, aber es fühlt sich eher wie eine Schiedsgerichtsbarkeit an.

Im Idealfall sollten wir uns keine Gedanken über Platzhalter machen. Wenn ich ein Prädikat für meine Ganzzahlen benötige, sollte ich einen Predicate<Integer> -Parameter deklarieren. Die Tatsache, dass ein Argument Predicate<Number> auch akzeptabel wäre, ist eine andere Geschichte. Es sollte die Aufgabe des Compilers sein, Predicate<Number> in Predicate<Integer> zu konvertieren - wir können es tun, ohne das existierende Java-Generics-System zu überholen, eine neue Konvertierungsregel ist alles, was benötigt wird. Man kann auch eine Konvertierungsbibliothek bereitstellen

%Vor%

Alle convert() -Methoden können mechanisch generiert werden.

Java 8 macht es ein wenig einfacher. Wir können immer noch nicht

%Vor%

Aber wir können

machen %Vor%

auch

%Vor%

entspricht f = forPredicate[2](pn) . In Java 8 benötigen wir selten forPredicate() etc, um zwischen Funktionstypen zu konvertieren.

    
irreputable 31.01.2013 22:03
quelle