Z Javadocs API dla java.lang.reflect.InvocationHandler:
InvocationHandler jest realizowany przez interfejs obsługi wywołania instancji proxy.
Dynamiczny serwer proxy implementuje interfejs, ale korzysta z procedury obsługi (OriginalClass) w celu zapewnienia podstawowych implementacji metod.
Aby odpowiedzieć na Twoje pytania:
- Kompilator pozwoli Ci rzucić tak długo jak nie ma wystarczających informacji, aby mieć pewność, że obsada nie może się udać. Zachowanie w czasie wykonywania testów rzutowania i instancji dla dynamicznych serwerów proxy opisano w javadoc dla java.lang.reflect.Proxy. Testy rzutowania i instancji będą skuteczne, jeśli są używane z interfejsami, ale nie, jeśli są używane z klasami.
- Nie można uzyskać dostępu do żadnych atrybutów za pomocą dynamicznego proxy, ponieważ implementuje interfejs, nie rozszerza klasy obsługi.
- Nie można uzyskać dostępu do metod, które nie zostały zadeklarowane w interfejsie za pomocą dynamicznego proxy, ponieważ implementuje interfejs, nie rozszerza klasy obsługi.
Wewnątrz implementacji dynamicznego proxy (np. W implementacji wywołania (...)) można uzyskać dostęp do członków obsługi za pomocą refleksji.
Oto niektóre kodu testu, który kiedyś sprawdzić moją odpowiedź:
// package ...;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import junit.framework.Assert;
import org.junit.Test;
public class TestDynamicProxy
{
@Test
public void testCast() throws Exception {
Foo foo = (Foo) TestProxy.newInstance(new FooImpl());
foo.bar(null);
System.out.println("Class: " + foo.getClass());
System.out.println("Interfaces: " + foo.getClass().getInterfaces());
Assert.assertNotNull(foo);
Assert.assertTrue(foo instanceof Foo);
Assert.assertFalse(foo instanceof FooImpl);
}
}
interface Foo
{
Object bar(Object obj) throws Exception;
}
class FooImpl implements Foo
{
public Object bar(Object obj) throws Exception {
return null;
}
}
class TestProxy implements java.lang.reflect.InvocationHandler
{
private final Object obj;
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new TestProxy(obj));
}
private TestProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Object result;
try {
result = m.invoke(obj, args);
}
catch (InvocationTargetException e) {
throw e.getTargetException();
}
catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}
return result;
}
}
Ten article ma wiele przydatnych informacji i przykładowy kod.
Czy jesteś pewien, że odsyłasz swoje proxy do dzieł OriginalClass? W moim rozumieniu, jeśli utworzyłeś proxy dla OriginalInterface, nie powinieneś być w stanie rzucić na OriginalClass –