Dies ist eine vereinfachte Version des fraglichen Codes. Eine generische Klasse verwendet eine andere Klasse mit generischen Typparametern und muss einen der generischen Typen an eine Methode mit varargs-Parametern übergeben:
class Assembler<X, Y> {
void assemble(X container, Y... args) { ... }
}
class Component<T> {
void useAssembler(T something) {
Assembler<String, T> assembler = new Assembler<String, T>();
//generates warning:
// Type safety : A generic array of T is
// created for a varargs parameter
assembler.assemble("hello", something);
}
}}
Gibt es eine korrekte Möglichkeit, den generischen Parameter an eine varargs-Methode weiterzugeben, ohne auf diese Warnung zu stoßen?
Natürlich so etwas wie
assembler.assemble("hello", new T[] { something });
funktioniert nicht, da Sie keine generischen Arrays erstellen können.
Antworten:
Abgesehen vom Hinzufügen
@SuppressWarnings("unchecked")
denke ich nicht.Dieser Fehlerbericht enthält weitere Informationen, läuft jedoch darauf hinaus, dass der Compiler Arrays generischer Typen nicht mag.
quelle
Tom Hawtin wies in einem Kommentar darauf hin, aber um es genauer zu sagen: Ja, Sie können dies an der Deklarationsstelle (anstelle der (möglicherweise vielen) Aufrufstellen) lösen: Wechseln Sie zu JDK7.
Wie Sie in Joseph Darcys Blog-Beitrag sehen können , akzeptierte die Project Coin-Übung zur Auswahl einiger kleiner inkrementeller Sprachverbesserungen für Java 7 Bob Lees Vorschlag , so etwas zuzulassen
@SuppressWarnings("varargs")
auf der Methodenseite , dass diese Warnung in Situationen, in denen dies bekannt war, verschwindet sicher.Dies wurde in OpenJDK mit diesem Commit implementiert .
Dies kann für Ihr Projekt nützlich sein oder auch nicht (viele Leute würden nicht gerne zu einer instabilen Vorabversion der JVM wechseln!), Aber vielleicht ist es das - oder vielleicht jemand, der diese Frage später findet (nachdem JDK7 veröffentlicht wurde) ) wird es nützlich finden.
quelle
Wenn Sie eine fließende Benutzeroberfläche suchen, können Sie das Builder-Muster ausprobieren. Nicht so prägnant wie Varargs, aber typsicher.
Eine statische, generisch typisierte Methode kann bei Verwendung des Builders einen Teil der Kesselplatte entfernen und gleichzeitig die Typensicherheit gewährleisten.
Der Bauarbeiter
Es benutzen
quelle
Collection
(in diesem Fall anArrayList
) wird dem Anrufer aufgezwungen, während er möglicherweise weiß, dass aLinkedList
geeigneter ist, oder ein unveränderliches Array selbst (wie die Varargs aus der OP-Frage). In einem nicht spezialisierten Anwendungsfall mag dies angemessen sein, aber nur darauf hinweisen, dass dies in gewisser Weise auch eine Einschränkung darstellt, abhängig vom Code, der dies umgibt, und Ihren Anforderungen.Das explizite Umwandeln von Parametern in Object beim Aufruf der vararg-Methode macht den Compiler glücklich, ohne auf @SuppressWarnings zurückzugreifen.
Ich glaube, das Problem hier ist, dass der Compiler herausfinden muss, welche konkrete Art von Array erstellt werden soll. Wenn die Methode nicht generisch ist, kann der Compiler Typinformationen aus der Methode verwenden. Wenn die Methode generisch ist, versucht sie, den Array-Typ anhand der beim Aufruf verwendeten Parameter zu ermitteln. Wenn die Parametertypen homogen sind, ist diese Aufgabe einfach. Wenn sie variieren, versucht der Compiler meiner Meinung nach zu klug zu sein und erstellt ein generisches Array vom Typ Union. Dann fühlt es sich gezwungen, Sie davor zu warnen. Eine einfachere Lösung wäre gewesen, Object [] zu erstellen, wenn der Typ nicht besser eingegrenzt werden kann. Die obige Lösung erzwingt genau das.
Um dies besser zu verstehen, spielen Sie mit Aufrufen der obigen Listenmethode im Vergleich zur folgenden list2-Methode.
quelle
Sie können der Methode seit Java 7 @SafeVarargs hinzufügen , und Sie müssen keine Anmerkungen zum Clientcode machen.
quelle
Sie können die Methoden überladen haben. Dies löst Ihr Problem nicht, minimiert aber die Anzahl der Warnungen (und ja, es ist ein Hack!)
quelle
Es ist ein sehr leicht zu lösendes Problem: Verwenden
List<T>
!Arrays vom Referenztyp sollten vermieden werden.
In der aktuellen Version von Java (1.7) können Sie die Methode mit markieren
@SafeVargs
der die Warnung vom Aufrufer entfernt wird. Seien Sie vorsichtig damit, und ohne ältere Arrays sind Sie immer noch besser dran.Siehe auch den technischen Hinweis zu verbesserten Compiler-Warnungen und -Fehlern bei Verwendung nicht überprüfbarer formaler Parameter mit Varargs-Methoden .
quelle
Wenn ich mit Arrays vom generischen Typ arbeite, muss ich einen Verweis auf den generischen Typ übergeben. Damit kann ich den generischen Code mit java.lang.reflect.Array erstellen.
http://java.sun.com/javase/6/docs/api/java/lang/reflect/Array.html
quelle