2015-11-20 36 views
6


Voglio creare una classe che ottiene un oggetto dalla definizione di una classe anonima da archiviare. Ho usato una classe tipizzata generica per ottenere ciò. Quindi voglio definire alcune operazioni usando le interfacce funzionali che ottengono questo oggetto come parametro con cui lavorare.
Il codice dice più delle parole. Quindi, dare un'occhiata a questo:classe anonima come parametro generico

public class Test<T> { 
    @FunctionalInterface 
    public interface operation<T> { 
     void execute(T object); 
    } 
    private T obj; 
    public Test(T _obj){ 
     obj = _obj; 
    } 
    public void runOperation(operation<T> op){ 
     op.execute(obj); 
    } 

    public static void main(String[] args){ 
     Test<?> t = new Test<>(new Object(){ 
      public String text = "Something"; 
     }); 
     t.runOperation((o) -> { 
      System.out.println(o.text); // text cannot be resolved 
     }); 
    } 
} 

mio problema è che o.text nella implementazione dell'interfaccia funzionale non può essere risolto. Questo è un qualche tipo di cancellazione?
La cosa interessante è che riesco a far funzionare questo codice quando implemento l'interfaccia funzionale nel costruttore.
Date un'occhiata a questo codice:

public class Test<T> { 
    @FunctionalInterface 
    public interface operation<T> { 
     void execute(T object); 
    } 
    private T obj; 
    private operation<T> op; 

    public Test(T _obj, operation<T> _op){ 
     obj = _obj; 
     op = _op; 
    } 
    public void runOperation(){ 
     op.execute(obj); 
    } 
    public static void main(String[] args){ 
     Test<?> t = new Test<>(new Object(){ 
      public String text = "Something"; 
     }, (o) -> { 
      System.out.println(o.text); 
     }); 
     t.runOperation(); 
    } 
} 

Questo funziona perfetto e stampa "Qualcosa". Ma cosa c'è di sbagliato nel mio primo approccio? Non ho davvero il problema qui.

+0

nuovo oggetto() { public String text = "Something"; }) – GKislin

risposta

1

Nella seconda parte del codice,

new Test<>(new Object(){ 
     public String text = "Something"; 
    }, (o) -> { 
     System.out.println(o.text); 
    }); 

compila perché il tipo argomento Test per la chiamata costruttore viene dedotta (in quanto l'operatore diamante è utilizzato), e si deduce al anonima digita che il primo argomento valuta (il tipo di classe anonima), e quindi il tipo del secondo argomento è operation<that anonymous class type>, che funziona.

Nel primo pezzo di codice, l'espressione

t.runOperation((o) -> { 
     System.out.println(o.text); // text cannot be resolved 
    }) 

non compila. Qui, il tipo di lambda viene dedotto in base al tipo di variabile t, che è Test<?>. Pertanto, l'argomento di runOperation deve essere operation<some unknown type>. L'unico argomento a runOperation che funzionerà qui è null.

1
Test<?> t = new Test<>(new Object(){ 
      public String text = "Something"; 
     }, (o) -> { 
      System.out.println(o.text); 
     }); 

Il compilatore qui sta sostituendo T in Test con la vostra classe anonima e dal momento che la classe contiene una variabile text è per questo che il secondo caso funziona.

+0

Ok, ma perché il compilatore non sostituisce T con la mia classe anonima nel primo caso? – ArcticLord

+0

Lo fa, ma il tipo della tua classe anonima è 'Object' che non ha una proprietà chiamata' text', quindi ottieni l'errore di compilazione. –

2

Il problema è che la classe anonima deve ancora conformarsi (estendere o implementare) un certo tipo e il tipo scelto è Object che non ha la proprietà text. Per fare riferimento a proprietà di qualche tipo, avrai bisogno di una vera classe o interfaccia con cui lavorare, così il compilatore può fare delle garanzie su quali proprietà e metodi sono disponibili sull'oggetto.

Questo funziona.

public class Test<T> { 

    public static class Data { 
     public String text; 
    } 

    @FunctionalInterface 
    public interface Operation<K> { 
     void execute(K object); 
    } 

    private T obj; 
    private Operation<T> op; 

    public Test(T obj) { 
     this.obj = obj; 
    } 

    public void runOperation(Operation<T> op) { 
     op.execute(obj); 
    } 

    public static void main(String[] args) { 
     Test<Data> t = new Test<>(new Data() {{ 
      this.text = "Something"; 
     }}); 

     t.runOperation((o) -> { 
      System.out.println(o.text); 
     }); 
    } 
} 
Problemi correlati