Entiendo que esto ocurre con Java 7 cuando se usan varargs con un tipo genérico;
Pero mi pregunta es ...
¿Qué significa exactamente Eclipse cuando dice "su uso podría contaminar el montón?"
Y
¿Cómo la nueva @SafeVarargs
anotación previene esto?
java
eclipse
generics
variadic-functions
hertzsprung
fuente
fuente
Possible heap pollution from parameterized vararg type
Respuestas:
La contaminación del montón es un término técnico. Se refiere a referencias que tienen un tipo que no es un supertipo del objeto al que apuntan.
Esto puede conducir a "inexplicables"
ClassCastException
s.@SafeVarargs
no evita esto en absoluto. Sin embargo, hay métodos que probablemente no contaminen el montón, el compilador simplemente no puede probarlo. Anteriormente, las personas que llamaban a tales API recibían advertencias molestas que eran completamente inútiles pero que tenían que ser suprimidas en cada sitio de llamadas. Ahora el autor de la API puede suprimirlo una vez en el sitio de declaración.Sin embargo, si el método no es seguro, los usuarios ya no serán advertidos.
fuente
Cuando declaras
public static <T> void foo(List<T>... bar)
el compilador lo convierte apublic static <T> void foo(List<T>[] bar)
luego apublic static void foo(List[] bar)
Entonces surge el peligro de que asigne por error valores incorrectos a la lista y que el compilador no active ningún error. Por ejemplo, si
T
es unString
, el siguiente código se compilará sin error pero fallará en tiempo de ejecución:Si revisó el método para asegurarse de que no contenga tales vulnerabilidades, puede anotarlo
@SafeVarargs
para suprimir la advertencia. Para interfaces, use@SuppressWarnings("unchecked")
.Si recibe este mensaje de error:
y está seguro de que su uso es seguro, entonces debería usarlo
@SuppressWarnings("varargs")
. Consulte ¿Es @SafeVarargs una anotación adecuada para este método? y https://stackoverflow.com/a/14252221/14731 para obtener una buena explicación de este segundo tipo de error.Referencias
fuente
Object[]
. Mientras no lancesObject[]
, parece que deberías estar bien.static <T> void bar(T...args) { ((Object[])args)[0] = "a"; }
. Y luego llamabar(Arrays.asList(1,2));
.Object[]
¿ por qué el compilador activaría una advertencia si no lo hago? Después de todo, debería ser bastante fácil verificar esto en tiempo de compilación (en caso de que no lo pase a otra función con una firma similar, en cuyo caso la otra función debería activar una advertencia). No creo que este sea realmente el núcleo de la advertencia ("Estás a salvo si no lanzas"), y todavía no entiendo en qué caso estoy bien.bar(Integer...args)
). Entonces, ¿cuál es el punto de esta advertencia?@SafeVarargs
no evita que suceda, sin embargo, exige que el compilador sea más estricto al compilar el código que lo usa.http://docs.oracle.com/javase/7/docs/api/java/lang/SafeVarargs.html explica esto con más detalle.
La contaminación del montón es cuando obtienes un
ClassCastException
al hacer una operación en una interfaz genérica y contiene otro tipo que el declarado.fuente
Cuando usa varargs, puede dar lugar a la creación de una
Object[]
para contener los argumentos.Debido al análisis de escape, el JIT puede optimizar esta creación de matriz. (Una de las pocas veces que lo he encontrado lo hace) No se garantiza que esté optimizado, pero no me preocuparía a menos que vea que es un problema en su generador de perfiles de memoria.
AFAIK
@SafeVarargs
suprime una advertencia del compilador y no cambia el comportamiento del JIT.fuente
@SafeVarargs
.La razón es porque los varargs dan la opción de ser llamados con una matriz de objetos no parametrizados. Entonces, si su tipo era List <A> ..., también se puede llamar con el tipo List [] no varargs.
Aquí hay un ejemplo:
Como puede ver, la Lista [] b puede contener cualquier tipo de consumidor y, sin embargo, este código se compila. Si usa varargs, entonces está bien, pero si usa la definición del método después del borrado de tipo - prueba nula (Lista []) - entonces el compilador no verificará los tipos de parámetros de la plantilla. @SafeVarargs suprimirá esta advertencia.
fuente