Java为给定接口生成代理类,并提供代理类的实例。但是当我们将代理对象类型转换为特定对象时,java是如何在内部处理这个问题的?这是特殊情况吗?
例如,我有类OriginalClass,它实现了OriginalInterface,当我通过传递OriginalInterface接口创建代理对象时,Java使用提供的接口中的方法创建了代理类ProxyClass,并提供了该类的对象(即ProxyClass)。如果我的理解是正确的,你能回答以下问题吗?
ProxyClass中键入OriginalClass的cast对象时,这是可行的,但是Java是如何允许这样做的呢?万一发生同样的情况?谢谢你,学生
发布于 2010-05-03 10:33:57
Java不允许将代理转换为具体的类。JDK代理(java.lang.reflect.Proxy)仅是接口的代理。得到的代理是ProxyX类型(X是一个数字),如果您试图将它转换为任何类,您将得到ClassCastException
因此,您的第二个和第三个问题是不相关的-代理没有支持一个具体的类。要实现这一点,您可以使用其他代理机制- CGLIB或javassist。它们使用ynamic子类,因此子类(代理)可以访问所有protected (和上面的)字段和方法。
发布于 2010-05-03 10:37:02
来自用于java.lang.reflect.InvocationHandler的API:
InvocationHandler是由代理实例的调用处理程序实现的接口。
动态代理实现接口,但使用处理程序(OriginalClass)提供方法的基本实现。
回答你的问题:
在动态代理的实现内部(例如,在调用的实现中(.)方法)可以使用反射访问处理程序的成员。
下面是我用来检查答案的一些测试代码:
// 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;
}
}这个文章有很多有用的信息和示例代码。
https://stackoverflow.com/questions/2757314
复制相似问题