2011-08-29 2 views
8

Se non si utilizza Java Generics, credo che non sia possibile avere due metodi nella stessa classe che differiscono solo nel loro tipo di ritorno.È possibile eseguire un overloading dei metodi con generici e modificare solo il tipo generico della firma del metodo?

In altre parole, questo sarebbe illegale:

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

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

È lo stesso vale quando sovraccaricare metodi che restituiscono un tipo generico che può implementare diverse interfacce, come se i seguenti due metodi erano presenti in la stessa definizione di classe:

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

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

questo sarebbe illegale?

+2

Hai provato a compilarlo? Un compilatore (conforme) ti dirà prontamente cosa è legale e cosa è illegale. Una domanda migliore sarebbe "perché è ... illegale?" se non capisci le ragioni. –

risposta

5

Questo è legale in quanto troppo il parametro di ingresso varia in base al tipo ..

Per questo motivo, in seguito è legale,

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

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

Ma in seguito non è,

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

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

Grazie ...

2

Questo funzionava bene.

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

Compilerà, ma dove si ha problemi è se Happy o Sad è una superclasse dell'altro.

Per esempio, il seguente 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; 
} 

Tuttavia, si esegue in problemi quando si tenta di compilare il seguente:

Integer test = sayHi(); 

In questo caso, semplicemente non è possibile aggiungere <Integer> al front perché Integer è ancora un numero e un intero.

Tuttavia il seguente compila

Double test2 = <Double>sayHi(); 

quindi in fondo fino a quando un oggetto Sad non può essere un'istanza di un oggetto Felice e viceversa, il codice dovrebbe funzionare fino a quando si chiama con la o di fronte del nome del metodo.

+0

come è possibile scrivere due metodi con la stessa firma del metodo, ma diversi tipi di ritorno e dire che compila, viola totalmente il concetto di overload dei metodi –

1

È possibile utilizzare un metodo generico per distinguere il metodo in Java. La JVM non vede questo tipo, tuttavia, a condizione che l'argomento o il tipo restituito siano diversi, verrà comunque compilato nel compilatore Sun/Oracle. Questo non viene compilato per il compilatore IBM/Eclipse.

Questo mostra che vuoi sta accadendo a livello di codice byte. http://vanillajava.blogspot.com/2011/02/with-generics-return-type-is-part-of.html

1

Questo è legale, come altri hanno già detto. Tuttavia, voglio sottolineare cosa succede quando i tipi si estendono l'un l'altro.

Diciamo che abbiamo due interfacce (lavora per le classi così basta cambiare la firma):

interface Emotion {} 
interface Happy extends Emotion {} 

E due funzioni:

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

Se un oggetto è conforme alla Emotion JVM sceglieranno foo1. Se un oggetto è conforme a Happy, la JVM sceglierà foo2 e non foo1. Avviso l'ordine di precedenza. Ecco come la JVM risolve l'ambiguità. Tuttavia, questo è valido solo quando si passa il parametro generico come argomento.