2015-11-20 13 views
6


Chcę utworzyć klasę, która pobiera obiekt z anonimowej definicji klasy do przechowywania. Użyłem ogólnej klasy, aby to osiągnąć. Następnie chcę zdefiniować niektóre operacje przy użyciu funkcjonalnych interfejsów, które pobierają ten obiekt jako parametr do pracy.
Kod mówi więcej niż słowa. Więc spójrz na to:anonimowa klasa jako parametr ogólny

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 
     }); 
    } 
} 

Mój problem polega na tym, że o.tekst w implementacji interfejsu funkcjonalnego nie może zostać rozwiązany. Czy to jakiś rodzaj skutku wymazania?
Interesujące jest to, że mogę uzyskać ten kod działający po wdrożeniu funkcjonalnego interfejsu w konstruktorze.
Wystarczy popatrzeć na ten kod:

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(); 
    } 
} 

Działa to doskonały i drukuje się „coś”. Ale co jest nie tak z moim pierwszym podejściem? Naprawdę nie mam tutaj problemu.

+0

nowy obiekt() { public String text = "Something"; }) – GKislin

Odpowiedz

1

W drugim kawałkiem kodu,

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

kompiluje ponieważ argument typu Test dla wywołania konstruktora jest wywnioskować (ponieważ operator diament jest używany), i jest to wywnioskować na anonimowy typ, do którego pierwszy argument się zwraca (anonimowy typ klasy), a tym samym typem drugiego argumentu jest operation<that anonymous class type>, który działa.

W pierwszym kawałkiem kodu, wyrażenie

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

nie kompiluje. W tym przypadku typ lambda jest wywnioskowany na podstawie typu zmiennej t, która jest Test<?>. Tak więc argument runOperation musi być operation<some unknown type>. Jedynym argumentem, który zadziała tutaj runOperation, jest null.

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

Kompilator tutaj jest zastąpienie T w Test z anonimowej klasy, a ponieważ klasa zawiera zmienną text dlatego 2nd sprawa działa.

+0

OK, ale dlaczego kompilator nie zastąpi T moją anonimową klasą w pierwszym przypadku? – ArcticLord

+0

To robi, ale typ twojej anonimowej klasy to 'Object', który nie ma właściwości o nazwie' text', więc dostajesz błąd kompilacji. –

2

Problem polega na tym, że Twoja anonimowa klasa nadal musi być zgodna z (rozszerzyć lub zaimplementować) jakiś typ, a wybrany przez ciebie typ to Object, który nie ma Twojej właściwości text. Aby odwoływać się do właściwości jakiegoś rodzaju, potrzebna jest rzeczywista klasa lub interfejs do pracy, aby kompilator mógł zagwarantować, jakie właściwości i metody są dostępne na obiekcie.

To działa.

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); 
     }); 
    } 
} 
Powiązane problemy