ppt - ¿Por qué el método de llamada con retorno genérico en una clase genérica es considerado inseguro por javac?
retorno generico java (4)
El tipo de un constructor (§8.8), método de instancia (§8.4, §9.4), o campo no estático (§8.3) M de un tipo sin formato C que no se hereda de sus superclases o superinterfaces es el tipo sin formato que corresponde al borrado de su tipo en la declaración genérica correspondiente a C.
Considere el siguiente código:
public class Main {
public static class NormalClass {
public Class<Integer> method() {
return Integer.class;
}
}
public static class GenericClass<T> {
public Class<Integer> method() {
return Integer.class;
}
}
public static void main(String... args) {
NormalClass safeInstance = new NormalClass();
Class<Integer> safeValue = safeInstance.method();
GenericClass unsafeInstance = new GenericClass();
Class<Integer> unsafeValue = unsafeInstance.method();
}
}
Si lo compilo con:
$ javac -Xlint:unchecked Main.java
Vuelve:
Main.java:16: warning: [unchecked] unchecked conversion
Class<Integer> unsafeValue = unsafeInstance.method();
^
required: Class<Integer>
found: Class
1 warning
Tenga en cuenta que solo el método genérico se considera inseguro, incluso si no se hace referencia a ningún tipo genérico en el tipo de devolución.
¿Es este un error javac
? ¿O hay una razón más profunda para esto que no estoy tomando en cuenta?
Esto podría tener que ver con la creación de instancias de GenericClass, que es un tipo parametrizado y, por lo tanto, se necesitan argumentos de tipo en él. La advertencia se desvanece si hacemos algo como lo siguiente
GenericClass<String> unsafeInstance = new GenericClass<String>();
OR
GenericClass<?> unsafeInstance = new GenericClass();
Según mi punto de vista, la referencia " unsafeInstance
" se refiere a una clase que es de naturaleza genérica en lugar de " safeInstance
". Por lo tanto, el compilador puede querer que la información de tipo se asocie a la referencia antes de llamar a cualquier método usándolo en el código.
Para ser compatible con el compilador Java 1.4, se supone que si se eliminan los argumentos genéricos en la declaración de tipo de instancia, se trabaja con la versión especial de la clase en la que no existe ningún genérico. Y emite una advertencia si mezcla un código no genérico de Java 1.4 con un código genérico de Java 1.5+. Es más fácil que tratar de averiguar si el tipo de retorno genérico de su método es realmente independiente de los parámetros. Siempre puedes @SuppressWarning
si no te gusta.
Se permitió que los tipos sin procesar garantizaran la compatibilidad con el código escrito antes de que se introdujeran los genéricos. Los tipos sin procesar funcionan simplemente ignorando toda la información de tipo de todos los argumentos de método y tipos de retorno, incluso la información de tipo que no está relacionada con el parámetro de tipo de la clase. Esto puede conducir a resultados extraños, como ha encontrado. Pero se vuelve aún más extraño que esto. Por ejemplo, esto compila.
public class Main {
public static class GenericClass<T> {
public void foo(Class<Integer> clazz) {
}
}
public static void main(String... args) {
GenericClass unsafeInstance = new GenericClass();
unsafeInstance.foo(String.class);
}
}