Ich verstehe, dass dies bei Java 7 auftritt, wenn Varargs mit einem generischen Typ verwendet werden.
Aber meine Frage ist ..
Was genau bedeutet Eclipse, wenn es heißt "seine Verwendung könnte möglicherweise den Haufen verschmutzen"?
Und
Wie @SafeVarargs
verhindert die neue Anmerkung dies?
java
eclipse
generics
variadic-functions
Hertzsprung
quelle
quelle
Possible heap pollution from parameterized vararg type
Antworten:
Haufenverschmutzung ist ein Fachbegriff. Es bezieht sich auf Referenzen, deren Typ kein Supertyp des Objekts ist, auf das sie verweisen.
Dies kann zu "unerklärlichen"
ClassCastException
s führen.@SafeVarargs
verhindert dies überhaupt nicht. Es gibt jedoch Methoden, die den Heap nachweislich nicht verschmutzen. Der Compiler kann dies einfach nicht beweisen. Bisher erhielten Anrufer solcher APIs nervige Warnungen, die völlig sinnlos waren, aber an jedem Anrufort unterdrückt werden mussten. Jetzt kann der API-Autor es einmal an der Deklarationsstelle unterdrücken.Wenn die Methode jedoch nicht sicher ist, werden Benutzer nicht mehr gewarnt.
quelle
Wenn Sie erklären
public static <T> void foo(List<T>... bar)
Der Compiler konvertiert es inpublic static <T> void foo(List<T>[] bar)
dann zupublic static void foo(List[] bar)
Es besteht dann die Gefahr, dass Sie der Liste fälschlicherweise falsche Werte zuweisen und der Compiler keinen Fehler auslöst. Wenn dies beispielsweise a ist,
T
wirdString
der folgende Code fehlerfrei kompiliert, schlägt jedoch zur Laufzeit fehl:Wenn Sie die Methode überprüft haben, um sicherzustellen, dass sie keine solchen Sicherheitsanfälligkeiten enthält, können Sie sie mit Anmerkungen versehen
@SafeVarargs
, um die Warnung zu unterdrücken. Verwenden Sie für Schnittstellen@SuppressWarnings("unchecked")
.Wenn Sie diese Fehlermeldung erhalten:
und Sie sind sicher, dass Ihre Verwendung sicher ist, dann sollten Sie
@SuppressWarnings("varargs")
stattdessen verwenden. Siehe Ist @SafeVarargs eine geeignete Anmerkung für diese Methode? und https://stackoverflow.com/a/14252221/14731 für eine nette Erklärung dieser zweiten Art von Fehler.Verweise:
quelle
Object[]
. Solange Sie nicht besetzenObject[]
, klingt es so, als ob es Ihnen gut gehen sollte.static <T> void bar(T...args) { ((Object[])args)[0] = "a"; }
. Und dann anrufenbar(Arrays.asList(1,2));
.Object[]
warum der Compiler eine Warnung auslösen würde, wenn ich es nicht tue? Es sollte schließlich ziemlich einfach sein, dies zur Kompilierungszeit zu überprüfen (falls ich es nicht an eine andere Funktion mit einer ähnlichen Signatur weitergebe, in diesem Fall sollte die andere Funktion eine Warnung auslösen). Ich glaube nicht, dass dies wirklich der Kern der Warnung ist ("Du bist in Sicherheit, wenn du nicht wirfst"), und ich verstehe immer noch nicht, in welchem Fall es mir gut geht.bar(Integer...args)
). Wozu dient diese Warnung dann?@SafeVarargs
verhindert dies nicht, erfordert jedoch, dass der Compiler beim Kompilieren von Code, der ihn verwendet, strenger ist.http://docs.oracle.com/javase/7/docs/api/java/lang/SafeVarargs.html erklärt dies ausführlicher.
Heap-Verschmutzung tritt auf, wenn Sie
ClassCastException
eine Operation an einer generischen Schnittstelle ausführen und diese einen anderen Typ als deklariert enthält.quelle
Wenn Sie varargs verwenden, kann dies dazu führen, dass ein
Object[]
Argument für die Argumente erstellt wird.Aufgrund der Escape-Analyse kann die JIT diese Array-Erstellung optimieren. (Eines der wenigen Male, bei denen ich festgestellt habe, dass dies der Fall ist.) Es ist nicht garantiert, dass es wegoptimiert wird, aber ich würde mir darüber keine Sorgen machen, es sei denn, Sie sehen, dass es ein Problem in Ihrem Speicherprofiler ist.
AFAIK
@SafeVarargs
unterdrückt eine Warnung des Compilers und ändert nicht das Verhalten der JIT.quelle
@SafeVarargs
.Der Grund dafür ist, dass varargs die Option bieten, mit einem nicht parametrisierten Objektarray aufgerufen zu werden. Wenn Ihr Typ also List <A> ... war, kann er auch mit dem Typ List [] non-varargs aufgerufen werden.
Hier ist ein Beispiel:
Wie Sie sehen können, kann List [] b jeden Verbrauchertyp enthalten, und dennoch wird dieser Code kompiliert. Wenn Sie varargs verwenden, ist das in Ordnung. Wenn Sie jedoch die Methodendefinition nach dem Löschen des Typs - void test (List []) - verwenden, überprüft der Compiler die Vorlagenparametertypen nicht. @SafeVarargs unterdrückt diese Warnung.
quelle