studio programacion móviles libros libro desarrollo desarrollar curso aprende aplicaciones java generics

java - móviles - manual de programacion android pdf



Método de anulación con tipo de devolución genérico (4)

¿Por qué quieres tener algo así como public abstract Class<? extends Interface> getMainClass(); public abstract Class<? extends Interface> getMainClass(); en lugar de public abstract Interface getMainClass(); ?

Creo que simplemente puede devolver una instancia de Interface , y luego, si la persona que llama desea tener acceso a la clase de tiempo de ejecución subyacente, simplemente puede llamar a getClass() en el objeto devuelto.

Esencialmente, creo que puedes simplemente hacer

public InterfaceImpl implements Interface { // ... }; public abstract class A { public abstract Interface getMainClass(); // ... } public class AImpl { return new InterfaceImpl(); } public class Main { public static void main(String[] args) { AImpl aImpl = new AImpl(); Interface i = aImpl.getMainClass(); System.out.println(i.getClass()); } }

Digamos que tengo una superclase que define el siguiente método abstracto

public abstract <T extends Interface> Class<T> getMainClass();

Ahora si quiero sobrescribirlo en alguna subclase

public Class<Implementation> getMainClass(){ return Implementation.class; }

Recibo una advertencia sobre la seguridad del tipo y la conversión sin marcar:

Tipo de seguridad: el tipo de retorno Class<Implementation> para getMainClass() del tipo SubFoo necesita conversión sin SubFoo para cumplir con la Class<Interface> del tipo SuperFoo

¿La Class<Implementation> corresponde a la Class<T> si <T extends Interface> ? ¿Hay alguna manera de deshacerse adecuadamente de la advertencia?


Considere la siguiente situación similar a la suya:

public class SuperFoo { public abstract <T extends Interface> List<T> getList(); } public class SubFoo extends SuperFoo { private List<Implementation> l = new ArrayList<Implementation>(); public List<Implementation> getList() { return l; } public void iterate() { for (Implementation i: l) ...; } } SubFoo subFoo = new SubFoo(); SuperFoo superFoo = subFoo; superFoo.getList().add(new AnotherImplementation()); // Valid operation! subFoo.iterate(); // Unexpected ClassCastException!

En este caso, la advertencia de conversión no verificada le advierte sobre la posibilidad de una ClassCastException inesperada.

Sin embargo, en su caso, cuando el tipo de devolución es Class<...> , no es un problema (por lo que yo entiendo), por lo que puede suprimir una advertencia legalmente:

@SuppressWarnings("unchecked") public Class<Implementation> getMainClass(){ ... }

Otra opción es hacer que SuperFoo sea ​​genérico:

public class SuperFoo<T extends Interface> { public abstract Class<T> getMainClass(); } public class SubFoo extends SuperFoo<Implementation> { public Class<Implementation> getMainClass() { ... } }

Para otra opción más (y tal vez la mejor), vea la respuesta de Stas Kurilin.


el tipo de devolución del método predominante debe ser un subtipo del tipo de devolución del método reemplazado.

Class<Impl> no es un subtipo de la Class<T> donde <T extends Interface> . T es desconocido aquí.

Class<Impl> es un subtipo de Class<? extends Interface> Class<? extends Interface> , por reglas de subtipificación.

algunas reglas de subtipado con respecto a los comodines:

para cualquier tipo X

  • A<X> es un subtipo de A<? extends X> A<? extends X>

  • A<X> es un subtipo de A<? super X> A<? super X>

si S es subtipo de T

  • A<? extends S> A<? extends S> es un subtipo de A<? extends T> A<? extends T>

  • A<? super T> A<? super T> es un subtipo de A<? super S> A<? super S>

Más concisamente, ( <: significa "es un subtipo de")

A<S> <: A<? extends S> <: A<? extends T> A<T> <: A<? super T> <: A<? super S>


prueba esto

public abstract Class<? extends Interface> getMainClass();

ejemplo reorganizado por tales advertencias java intenta prevenir casos como este

class OtherImpl implements Interface{ } A a = new B();//where A - your abstract class and B - implementation Class<OtherImpl> other = a.<OtherImpl>getMainClass();//some broken think, But _without_ runtime exception

Como @axtavt mencionó el ejemplo se rompió. Lo reorganicé