El siguiente código no se compila en OpenjDK 11. Me parece que test1 en B debería anular test1 en A, porque:
Tomé un descompilador y descompilé cada clase por separado. El código compilado realmente funcionó como esperaba. Reemplazó U extiende Número con Número, T extiende Integer con Integer y así sucesivamente. Pero cuando intento compilar las dos clases juntas, aparece un error en la segunda clase que dice que la prueba en la segunda clase no anula un método en la primera.
Me estoy perdiendo algo grande o pequeño aquí. Y probablemente esté relacionado con 5. Tal vez los tipos no sean covariantes. ¿Me puedes ayudar?
class A { <U extends Number, T extends Number> U test(T test) { System.out.println("In A.test(T test)"); return null; } //Decompiler shows that the above method erases to // Number test(Number test) // Just like the method below. Number test2(Number test) { return null; } } class B extends A { //Unsuccessful override. Compiler error. @Override <U extends Integer, T extends Number> U test(T test) { System.out.println("In B.test(T tesT)"); return null; } //Decompiler shows that the above method erases to //Integer test(Number test) //Just like the method bellow. //Successful override @Override Integer test2(Number test) { return null; } }La razón por la que sus métodos test producen un error es porque tienen firmas diferentes totalmente no relacionadas. Tenga en cuenta que la firma de un método consiste en su nombre, lista de parámetros y parámetros de tipo .
Cita de la especificación del lenguaje Java:
Dos métodos o constructores, M y N, tienen la misma firma si tienen el mismo nombre, los mismos parámetros de tipo (si los hay) (§8.4.4) y, después de adaptar los tipos de parámetros formales de N a los parámetros de tipo de M, los mismos tipos de parámetros formales.
Fundamentalmente, sus dos métodos test no tienen los mismos parámetros de tipo , porque U en A.test tiene un límite diferente de U en B.test .
Dos métodos o constructores M y N tienen los mismos parámetros de tipo si se cumplen las dos condiciones siguientes:
M y N tienen el mismo número de parámetros de tipo (posiblemente cero).
Donde A1, ..., An son los parámetros de tipo de M y B1, ..., Bn son los parámetros de tipo de N, sea θ=[B1:=A1, ..., Bn:=An]. Entonces, para todo i (1 ≤ i ≤ n), la cota de Ai es del mismo tipo que θ aplicada a la cota de Bi.
Piense en lo que sucedería si B.test A.test . ¡Podría pasar un tipo al parámetro de tipo U que está fuera de sus límites!
A a = new B(); // This will call B.test, and U is Double, T is Integer // but U should extends Integer! Double x = a.test((Integer)0);Para obtener más información , estas son las reglas precisas para cuando ocurre la anulación. Tenga en cuenta que los criterios n.º 4 y n.º 5 de su lista no se consideran realmente. Son solo requisitos adicionales que hacen que su código no se compile si los rompe. Un método todavía está "definido" para anular otro incluso si rompe esos requisitos. Se enumeran aquí en el JLS.