2011-04-03 12 views
16

Tengo el siguiente código:Tipo Borrado y sobrecarga en Java: ¿Por qué funciona esto?

public class Pair< T, U > { 
    public T first; 
    public U second; 
} 
public class Test { 
    public int method(Pair< Integer, Integer > pair) { 
     return 0; 
    } 
    public double method(Pair< Double, Double > pair) { 
     return 1.0; 
    } 
} 

En realidad, esto compila y funciona como uno esperaría. Pero si los tipos de devolución están hechos para ser iguales, esto no se compila, con el esperado "nombre de choque: método (Pair) y método (Pair) tienen el mismo borrado"

Dado que el tipo de devolución no es ' t parte de la firma del método, ¿cómo es posible esta sobrecarga?

+1

posible duplicado de [el código genérico de Java compila con javac, falla con Eclipse Helios] (http://stackoverflow.com/questions/3452859/java-generics-code-compiles-with-javac-fails-with-eclipse- helios) – BalusC

Respuesta

9

Considere los 4 métodos siguientes

  Java code      bytecode 

m1: Byte f(List<Byte> list)   f List -> Byte 
m2: Long f(List<Byte> list)   f List -> Long 
m3: Byte f(List<Long> list)   f List -> Byte 
m4: Long f(List<Long> list)   f List -> Long 

De acuerdo con la corriente del lenguaje Java Spec,

  • M1 y M2 no pueden coexistir, ni puede M3 y M4. porque tienen los mismos tipos de parámetros.

  • m1 y m3 pueden coexistir, también pueden m1 y m4. porque tienen diferentes tipos de parámetros.

Pero javac 6 solo permite m1 + m4, no m1 + m3. Eso está relacionado con la representación de bytecode de métodos, que incluye tipos de devolución. Por lo tanto, m1 + m4 están bien, pero no m1 + m3.

Esto es un error donde las especificaciones de Java y JVM no se ven a los ojos. No hay una forma "correcta" para javac.

Mientras apesta, la buena noticia es que la sobrecarga es un vanidad, no una necesidad. Siempre podemos usar nombres diferentes, más descriptivos y distintos para estos métodos.

+1

Según lo que debería decir la especificación (según varias entradas en la base de datos de errores de Java), no pueden coexistir dos de estos métodos, ya que tienen los mismos tipos de parámetros ** después de la borradura tipo **. –

+0

Gracias por la representación de bytecode; eso hace que el problema sea muy claro. Por lo tanto, aunque la "firma de método" normalmente se refiere solo a los parámetros, una firma de método en bytecode incluye el tipo de devolución. –

+0

Y según [este error] (http://bugs.sun.com/view_bug.do?bug_id=6182950) incluso m1 + m4 sería ilegal en javac7. Es una pena, ya que a veces es muy útil tener pocos métodos sobrecargados en forma de 'SomeType f (SomeClass ) '. (Como en mi respuesta a [esta pregunta] (http://stackoverflow.com/q/6641723/648313)) – Idolon

6

La sobrecarga se realiza en tiempo de compilación.

Aunque los parámetros genéricos se borran en tiempo de ejecución, aún están disponibles para que el compilador resuelva las sobrecargas.

-1

Creo que en realidad está buscando escribir mal. Al decir que el primer método toma Pair, le está dando un tipo muy específico. Es como decir el método (String, String). El segundo método de Pair es como decir el método (Persona, Persona). Esto también es muy específico en un nivel de tipeo. Si cambiara sus métodos para ser método (Pair <T,U>, Pair <T,U>) y lo tuviera dos veces, rompería la compilación.

Respuesta tan corta: ya que ha escrito fuertemente Pair para significar dos cosas diferentes, los genéricos no están en juego, simplemente escribiendo la regla.

1

Una firma de método Java realmente incluye el tipo de devolución; si alguna vez ha trabajado con JNI, ha visto descripciones de tipo como (LPair;) D y (LPair;) I. Ese último carácter denota los tipos de devolución de sus dos métodos. Aunque la regla del lenguaje Java es que los parámetros deben diferir para dos métodos sobrecargados, el formato del archivo de clase puede realmente distinguir métodos basados ​​solo en sus tipos de retorno. Cuando hay información de tipo genérico para permitir que el compilador resuelva las sobrecargas en función de sus argumentos, siempre que los tipos de devolución sean diferentes, las borraduras tendrán diferentes firmas y todo funciona bien. Si los tipos de devoluciones son los mismos, sin embargo, luego de borrarlos, los métodos tienen la misma firma, el archivo de clase no puede notar la diferencia y usted tiene un problema.

+0

Esta es la mejor explicación que pude encontrar en este lugar. Gracias – kaustubh

Cuestiones relacionadas