2012-12-08 11 views
11

W języku Java, czy możliwe jest zastąpienie metod w klasie utworzonej przy użyciu reflection? Na przykład, że mam następujące klasy:Jak mogę przesłonić metody w Javie podczas tworzenia obiektu za pomocą odbicia?

public class MyObject 
{ 
    public String foo, bar; 

    public MyObject(String foo) 
    { 
     this.foo = foo; 
     this.bar = foo + "bar"; 
    } 

    public void setBar(String bar) 
    { 
     this.bar = bar; 
    } 
} 

I w jednej klasie Chcę utworzyć go bezpośrednio i zastąpić swoją metodę setBar następująco:

MyObject obj = new MyObject("something") 
{ 
    @Override 
    public void setBar(String bar) 
    { 
     this.bar = this.foo; 
    } 
}; 

czy istnieje sposób aby przesłonić metodę w ten sam sposób używając refleksji? Może coś takiego? :

Class<?> _class = Class.forName("com.example.MyObject"); 
Constructor<?> _constructor = _class.getConstructor(new Class<?>[]{String.class}); 
Method m = _class.getMethod("setBar", new Class<?>[]{String.class}); 
Object obj = _constructor.newInstance("Foo String") 
{ 
    m = new Method(new Class<?>[]{String.class}) 
    { 
     System.out.println("Foobar"); 
    } 
}; 

Jeśli nie, czy są inne sposoby na to, lub zewnętrzna biblioteka, która może pomóc? Szukam sposobu dodania detektorów do metody ustawiającej w celu zmiany wartości wiązania.

+1

Potrzebujesz biblioteki dynamicznego generowania kodu, na przykład * javassist *. –

Odpowiedz

10

Nie, nie jest to możliwe na podobieństwo przykładu.

W przykładzie kompilator Java stworzy dwie odrębne klasy:

MyObject.class 
MyObject$1.class 

Ten ostatni jest jednym z metodą zmiany. W tym przypadku jest to anonimowa klasa wewnętrzna (Zobacz Java tutorial documentation)

Ale jest bardziej złożone rozwiązanie obejmujące biblioteki tkackie kodu bajtowego. Biblioteki takie jak cglib, asm, javassist itp. Dają możliwość dynamicznego tworzenia nowych klas w czasie wykonywania i ładowania ich.

Javassist ma samouczek na temat, jak add methods to classes at runtime. Powinno być możliwe dostosowanie go w celu dodania/zastąpienia metody, coś takiego:

CtClass origClazz = ClassPool.getDefault().get("org.example.MyObject"); 
CtClass subClass = ClassPool.getDefault().makeClass(cls.getName() + "New", origClazz); 
CtMethod m = CtNewMethod.make(
      "public void setBar(String bar) { this.bar = bar; }", 
      subClass); 
subClass .addMethod(m); 
Class clazz = cc.toClass(); 
+0

To jest dokładnie to, czego szukałem - ale zdecydowanie mogę to dopasować. Dzięki! – Phil

0

Nie, to, o co prosisz, to coś w rodzaju kompilacji środowiska wykonawczego. Chociaż nie jest to niemożliwe, to z pewnością nie jest to coś, co zapewnia interfejs API Reflect.

2

Jeśli wracasz przedmiot typ interfejsu, można użyć Proxy.newProxyInstance uzyskać instancję interfejsu, który dynamicznie wysyła metody wywołania do obiektu InvocationHandler których można napisać cokolwiek zrobić niestandardowe zachowanie chcesz.

Powiązane problemy