首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Java中,cast的实例和类型(即(ClassName))如何在代理对象上工作?

在Java中,cast的实例和类型(即(ClassName))如何在代理对象上工作?
EN

Stack Overflow用户
提问于 2010-05-03 10:11:24
回答 2查看 7.5K关注 0票数 8

Java为给定接口生成代理类,并提供代理类的实例。但是当我们将代理对象类型转换为特定对象时,java是如何在内部处理这个问题的?这是特殊情况吗?

例如,我有类OriginalClass,它实现了OriginalInterface,当我通过传递OriginalInterface接口创建代理对象时,Java使用提供的接口中的方法创建了代理类ProxyClass,并提供了该类的对象(即ProxyClass)。如果我的理解是正确的,你能回答以下问题吗?

  1. 当我在类ProxyClass中键入OriginalClass的cast对象时,这是可行的,但是Java是如何允许这样做的呢?万一发生同样的情况?
  2. 据我所知,Java只使用方法创建代理类,但是当我试图访问该对象的属性时会发生什么呢?
  3. 只有接口方法是在代理中实现的,但是当我尝试访问一个不是在接口中并且只在类中提到的方法时会发生什么呢?

谢谢你,学生

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-05-03 10:33:57

Java不允许将代理转换为具体的类。JDK代理(java.lang.reflect.Proxy)仅是接口的代理。得到的代理是ProxyX类型(X是一个数字),如果您试图将它转换为任何类,您将得到ClassCastException

因此,您的第二个和第三个问题是不相关的-代理没有支持一个具体的类。要实现这一点,您可以使用其他代理机制- CGLIB或javassist。它们使用ynamic子类,因此子类(代理)可以访问所有protected (和上面的)字段和方法。

票数 11
EN

Stack Overflow用户

发布于 2010-05-03 10:37:02

来自用于java.lang.reflect.InvocationHandler的API:

InvocationHandler是由代理实例的调用处理程序实现的接口。

动态代理实现接口,但使用处理程序(OriginalClass)提供方法的基本实现。

回答你的问题:

  1. 编译器将允许您进行强制转换,只要它没有足够的信息来确定强制转换不能成功。java.lang.reflect.Proxy的javadoc描述了动态代理的强制转换和测试实例的运行时行为。如果与接口一起使用,则转换和测试实例将获得成功,但如果用于类,则不会成功。
  2. 您不能使用动态代理访问任何属性,因为它实现了接口,因此它不扩展处理程序类。
  3. 不能使用动态代理访问接口中未声明的任何方法,因为它实现了接口,因此它不扩展处理程序类。

在动态代理的实现内部(例如,在调用的实现中(.)方法)可以使用反射访问处理程序的成员。

下面是我用来检查答案的一些测试代码:

代码语言:javascript
复制
// 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;
    }
}

这个文章有很多有用的信息和示例代码。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2757314

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档