useful parameter method example are java generics

method - java generics parameter



No coinciden los tipos de Class Generics (3)

Eliminar el condicional y el error es un poco mejor ...

public class Test { public static void main(String args[]) { Test t = new Test(); t.testT(null); } public <T extends Test> void testT(Class<T> type) { Class<T> testClass = Test.class; System.out.println(testClass); } } Test.java:10: incompatible types found : java.lang.Class<Test> required: java.lang.Class<T> Class<T> testClass = Test.class;

Tengo el siguiente código que no se compilará y aunque hay una forma de compilarlo, quiero entender por qué no se está compilando. ¿Alguien me puede aclarar específicamente por qué recibo el mensaje de error que publicaré al final, por favor?

public class Test { public static void main(String args[]) { Test t = new Test(); t.testT(null); } public <T extends Test> void testT(Class<T> type) { Class<T> testType = type == null ? Test.class : type; //Error here System.out.println(testType); } }

Type mismatch: cannot convert from Class<capture#1-of ? extends Test> to Class<T>

Al Test.class en Class<T> esto se compila con una advertencia de Unchecked cast y se ejecuta perfectamente.


Supongamos que extiendo Test:

public class SubTest extends Test { public static void main(String args[]) { Test t = new Test(); t.testT(new SubTest()); } }

Ahora, cuando invoca testT , el parámetro de tipo <T> es SubTest , lo que significa que la variable testType es una Class<SubTest> . Test.class es del tipo Class<Test> , que no se puede asignar a una variable del tipo Class<SubTest> .

Declarando la variable testType como Class<? extends Test> Class<? extends Test> es la solución correcta; lanzar a Class<T> está ocultando un problema real.


La razón es que Test.class es del tipo Clase <Prueba>. No puede asignar una referencia de tipo Clase <Prueba> a una variable de tipo Clase <T> ya que no son la misma cosa. Esto, sin embargo, funciona:

Class<? extends Test> testType = type == null ? Test.class : type;

El comodín permite que las referencias Class <T> y Class <Test> se asignen a testType.

Existe una gran cantidad de información sobre el comportamiento genérico de Java en Angelika Langer Java Generics FAQ . Proporcionaré un ejemplo basado en parte de la información que utiliza la jerarquía de núcleo de la clase Number API de Java.

Considera el siguiente método:

public <T extends Number> void testNumber(final Class<T> type)

Esto es para permitir que las siguientes declaraciones se compilen con éxito:

testNumber(Integer.class); testNumber(Number.class);

Pero lo siguiente no se compilará:

testNumber(String.class);

Ahora considere estas declaraciones:

Class<Number> numberClass = Number.class; Class<Integer> integerClass = numberClass;

La segunda línea no puede compilar y produce este error Type mismatch: cannot convert from Class<Number> to Class<Integer> . Pero Integer amplía Number , entonces, ¿por qué falla? Mira estas dos declaraciones para ver por qué:

Number anumber = new Long(0); Integer another = anumber;

Es bastante fácil ver por qué la 2da línea no se compila aquí. No puede asignar una instancia de Number a una variable de tipo Integer porque no hay forma de garantizar que la instancia Number sea ​​de un tipo compatible. En este ejemplo, el Number es en realidad un Long , que ciertamente no se puede asignar a un Integer . De hecho, el error también es una discrepancia de tipo: Type mismatch: cannot convert from Number to Integer .

La regla es que una instancia no se puede asignar a una variable que sea una subclase del tipo de la instancia, ya que no hay garantía de que sea compatible.

Los genéricos se comportan de manera similar. En la firma del método genérico, T es solo un marcador de posición para indicar lo que el método le permite al compilador. Cuando el compilador encuentra testNumber(Integer.class) , esencialmente reemplaza T con Integer .

Los comodines agregan flexibilidad adicional, ya que se compilará lo siguiente:

Class<? extends Number> wildcard = numberClass;

¿Desde Class<? extends Number> Class<? extends Number> indica cualquier tipo que sea un Number o una subclase de Number esto es perfectamente legal y potencialmente útil en muchas circunstancias.