2016-07-08 21 views
5

Ho riscontrato uno strano problema nel mio progetto. Ora ho semplificato il problema e scritto un piccolo esempio per illustrare la mia confusione:Cosa c'è di sbagliato con la parola chiave "super" in Java tipo generico

public class Question { 
    class Q1 {} 

    class Q2 extends Q1 {} 

    interface In<T> { 
     void f(T t); 
    } 

    List<Q2> list; 

    void f(In<? super List<? super Q2>> in) { 
     in.f(list); 
    } 

    static void g() { 
     Question question = new Question(); 
     In<Collection<Q1>> in1 = new In<Collection<Q1>>() { 
      @Override 
      public void f(Collection<Q1> o) {} 
     }; 
     In<List<Q2>> in2 = new In<List<Q2>>() { 
      @Override 
      public void f(List<Q2> o) {} 
     }; 
     question.f(in1); //Error! 
     question.f(in2); //Error! 
    } 
} 

Il mio obiettivo è quello di rendere il metodo f(In<? super List<? super Q2>>) più flessibile. Posso passare al metodo in1 o in2. Ma nessuno dei due può essere passato! Che c'è?

Forse this answer avrà un senso. Ma la mia domanda è diversa !!! Il mio tipo generico è In<? super List<? super Q2>>, un tipo generico all'interno di un tipo generico.

+0

@AndyTurner "tutto corrisponde? Super Q2" quindi perché 'question.f (in1)' è un errore? puoi cancellare di più? – Jerry06

+0

@ Jerry06 Penso di aver interpretato male la domanda. Riaperto. –

risposta

0
In<Collection<? extends Q1>> in1 = new In<Collection<? extends Q1>>() { 
      @Override 
      public void f(Collection<? extends Q1> o) {} 
     }; 
     In<List<? extends Q2>> in2 = new In<List<? extends Q2>>() { 
      @Override 
      public void f(List<? extends Q2> o) {} 
     }; 
+0

'extend' è diverso. È più semplice. Si prega di cambiarlo in 'super' e vedere cosa succede. –

+0

sì. Stesso errore con super – Gangadhar

2

Un tipo generico di forma A<? extends B> significa che il ? può essere sostituita da qualsiasi B o super-tipo di B. Pertanto, List<? super Q2> significa qualcosa come: List<Object>, List<Q1> o List<Q2>.

Anche se Q1 è un super-tipo di Q2, List<Q1> non è un super-tipo di List<Q2>. Ciò significa che l'unico super tipo comune di List<Object>, List<Q1> e List<Q2> è Object. Quindi l'unica cosa che puoi passare al tuo metodo f è un In<Object>.

Il modo in cui è necessario risolverlo dipende dalla flessibilità effettivamente necessaria: che tipo di oggetti si desidera passare a f e cosa si vuole fare con tali oggetti?

+0

Cosa dire '> '? E cosa dovrei fare se voglio passare qualsiasi sottoclasse di 'Collection' a' f'? –