2011-08-29 15 views
8

Si no usa Java Generics, creo que no es posible tener dos métodos en la misma clase que difieran solo en su tipo de devolución.¿Se puede sobrecargar el método con genéricos y solo cambiar el tipo genérico de la firma del método?

En otras palabras, esto sería ilegal:

public HappyEmotion foo(T emotion) { 
    // do something 
} 

public SadEmotion foo(T emotion) { 
    // do something else 
} 

es el mismo cierto cuando la sobrecarga de métodos que devuelven un tipo genérico que puede implementar diferentes interfaces, como si los dos métodos siguientes estaban presentes en la misma definición de clase:

public <T extends Happy> T foo(T emotion) { 
    // do something 
} 

public <T extends Sad> T foo(T emotion) { 
    // do something else 
} 

Sería esto ilegal?

+2

¿Intentaste compilarlo? Un compilador (conforme) le dirá con prontitud qué es legal y qué es ilegal. Una mejor pregunta sería '¿por qué es ... ilegal?' si no entiendes las razones –

Respuesta

5

Esto es legal ya que el parámetro de entrada también es diferente según el tipo ..

Por esta razón, siguientes son legales,

public <T extends Happy> T foo(T emotion) { 
    // do something 
} 

public <T extends Sad> T foo(T emotion) { 
    // do something else 
} 

Pero sigue no es,

public <T extends Happy> String foo(T emotion) { 
    // do something 
} 

public <T extends Happy> T foo(T emotion) { 
    // do something else 
} 

Gracias ...

2

Esto funcionó muy bien.

public class Main { 
    public static void main(String[] args){ 
     Main main = new Main(); 
     main.foo("hello"); 
     main.foo(new Integer(5)); 
    } 

    public <T extends String> T foo(T emotion) { 
     return (T) "test"; 
    } 

    public <T extends Integer> T foo(T emotion) { 
     Integer integer = 5; 
     return (T) integer; 
    } 
} 
2

Se compilará, pero cuando te metes en problemas es si Happy o Sad es una superclase de la otra.

Por ejemplo, la siguiente se compila:

public <T extends Number> T sayHi() { 
    System.out.println("number"); 
    return null; 
} 

public <T extends Integer> T sayHi() { 
    System.out.println("integer"); 
    return null; 
} 

Sin embargo, se encuentra con problemas cuando intenta compilar el siguiente:

Integer test = sayHi(); 

En este caso, simplemente no se puede añadir <Integer> a la frontal porque Integer sigue siendo un Número y un Entero.

Sin embargo, el siguiente compila

Double test2 = <Double>sayHi(); 

así que básicamente el tiempo que un objeto triste no puede ser una instancia de un objeto feliz y viceversa, el código debería funcionar siempre y cuando se le llama con el o delante del nombre del método.

+0

¿Cómo se pueden escribir dos métodos con la misma firma de método, pero diferentes tipos de devolución y decir que se compila, viola por completo el concepto de sobrecarga de método –

1

Puede usar genéricos para distinguir el método en Java. La JVM no ve este tipo; sin embargo, siempre que el argumento o el tipo de retorno sea diferente, aún se compilará en el compilador Sun/Oracle. Esto no se compila para el compilador de IBM/eclipse.

Esto muestra lo que está sucediendo en el nivel de código de bytes. http://vanillajava.blogspot.com/2011/02/with-generics-return-type-is-part-of.html

1

Esto es legal, como han dicho otros. Sin embargo, quiero señalar lo que sucede cuando los tipos se extienden entre sí.

Digamos que tenemos dos interfaces (funciona para las clases que también acaba de cambiar la firma):

interface Emotion {} 
interface Happy extends Emotion {} 

Y dos funciones:

<T extends Emotion> void foo(T obj) {} // Referred as foo1 
<T extends Happy> void foo(T obj) {} // Referred as foo2 

Si un objeto se ajusta a la emoción la JVM elegiremos foo1. Si un objeto cumple con Happy, la JVM elegirá foo2 y no foo1. Observe el orden de precedencia. Así es como la JVM resuelve la ambigüedad. Sin embargo, esto solo es válido cuando pasa el parámetro genérico como argumento.

Cuestiones relacionadas