Me encontré con un problema con la jerarquía de clases en una función genérica. Necesito hacer cumplir que, con las dos clases T y U especificadas en la función, una es hija de la otra. Me sorprendió mucho que la construcción <T extends U> no impone en absoluto una relación padre-hijo de U y T En su lugar, también permite que T y U sean del mismo tipo.
Esto crea un problema porque parece que en un caso en el que U extends T , Java no indicará el error, sino que felizmente deducirá que ambos objetos son del tipo T (lo cual es cierto, sin duda) y luego compilará y ejecutará el código sin ningún tipo de error. queja.
Aquí hay un ejemplo que ilustra el problema:
public class MyClass { public static void main(String args[]) { Foo foo = new Foo(); Bar bar = new Bar(); // This code is written as intended System.out.println( justTesting(foo, bar) ); // This line shouldn't even compile System.out.println( justTesting(bar, foo) ); } static interface IF { String get(); } static class Foo implements IF { public String get(){return "foo";} } static class Bar extends Foo { public String get(){return "bar";} } static <G extends IF , H extends G> String justTesting(G g, H h) { if (h instanceof G) return h.get() + " (" + h.getClass() + ") is instance of " + g.getClass() + ". "; else return "it is the other way round!"; } }Y esta es la salida:
bar (class MyClass$Bar) is instance of class MyClass$Foo. foo (class MyClass$Foo) is instance of class MyClass$Bar.Necesito asegurarme de que el compilador observe la relación padre-hijo de las clases genéricas. ¿Hay alguna forma de hacer eso?
Se compila, porque IF es un "límite superior" tanto para H como para G
Significa: Los genéricos no son tan "dinámicos" como pensamos, y también podríamos escribir:
static <G extends IF, H extends IF> ... // just pointing out that G *could* differ from HSin tener en cuenta el control nulo, es esto lo que quieres:
static <G extends IF, H extends G> String justTesting(G g, H h) { if (g.getClass().isAssignableFrom(h.getClass())) { return h.get() + " (" + h.getClass() + ") is instance of " + g.getClass() + ". "; } else { return "it is the other way round!"; } }?
Huellas dactilares:
bar (class com.example.test.generics.Main$Bar) is instance of class com.example.test.generics.Main$Foo. it is the other way round!Y cuidado con las "clases anónimas", por ejemplo:
System.out.println( justTesting( new IF() { @Override public String get() { return "haha"; } }, foo) ); System.out.println( justTesting( foo, new IF() { @Override public String get() { return "haha"; } } ) );imprime ambos "¡es al revés!", por lo que la decisión aquí no es ese "binario".