środa, października 08, 2008

Sztuczki tropiciela błędów, part 4

Próbowałem dziś zrobić coś co podobno jest w Java'ie niemożliwe, czyli zadziedziczyć po klasie finalnej.
Moja pierwsza próba jest taka sobie...
Użyłem tutaj proxy z odbić, które to proxy wg. teorii zapewnia nam, że w momencie wołania kodu z naszej "sproxowanej" klasy, wykonany najpierw zostanie kod proxy....
Poniżej kod, ktoś spróbuje zgadnąć jaki będzie wynik działania tego programiku? ;-)
import java.lang.reflect.Method;

public class ClassProxy {
interface Foo {
void doSth();
}

// final class
static final class FooImp implements Foo {
public void doSth() {
System.out.println("doSth...");
}
}

static class DebugProxy implements java.lang.reflect.InvocationHandler {
private Object obj;
private static Object extendImpl;

public static Object newInstance(Object obj, Object fakeExtendingObject) {
extendImpl = fakeExtendingObject;
return java.lang.reflect.Proxy.newProxyInstance(obj.getClass()
.getClassLoader(), obj.getClass().getInterfaces(),
new DebugProxy(obj));
}

private DebugProxy(Object obj) {
this.obj = obj;
}

public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
Object result;
Object currentObject = obj;
try {
Method newMethod = m;
newMethod = extendImpl.getClass().getDeclaredMethod(
m.getName(), m.getParameterTypes());
currentObject = extendImpl;
result = newMethod.invoke(currentObject, args);
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: "
+ e.getMessage());
}
return result;
}
}

public static void main(String[] args) {
Foo str = (Foo) DebugProxy.newInstance(new FooImp(), new Object() {
public void doSth() {
System.out.println("Toster!!!!");
}
}); // What we will see as a result??? :-) str.doSth(); }}
}
}
Wg. zdrowego rozsądku powinien to być napis "doSth...", jednak wynikiem będzie "Toster!!!!".
Udało się teoretycznie "wstrzyknąć" nasz kod do obiektu oryginalnego, ale jakoś tak mało przekonująco.... Zawsze dobrze wiedzieć, że się tak da ;-) Ale funkcjonalnie niewiele się to różni od tego co opisywałem w Sztuczkach tropiciela błędów, part 3 i w jednej z technik ze Sztuczek tropiciela błędów, part 2.
Przez to wszystko nie jestem jakoś szczególnie zadowolony z tej sztuczki.... ;-)


Podobne postybeta
Sztuczki tropiciela błędów, part 3 - hackujemy klasy finalne ;-)
Niecne wykorzystanie refleksji... czyli jak poszukać tekstu w drzewie obiektów? ;-)
Java 8 nadchodzi....
Dodajmy 3 klasy do SDK Java'y ;-)
Problem języka