【问题标题】:In Java how instance of and type cast(i.e (ClassName)) works on proxy object?在Java中,实例和类型转换(即(ClassName))如何在代理对象上工作?
【发布时间】:2011-02-14 23:38:29
【问题描述】:

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

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

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

谢谢, 学生

【问题讨论】:

  • 您确定将您的代理转换为 OriginalClass 有效吗?据我了解,如果您为 OriginalInterface 创建了代理,您将无法转换为 OriginalClass
  • 很好的问题,并且在强制转换和 instanceof 逻辑中必须有一些代理类型的特殊大小写。如果有人知道要查看 JDK 源代码的哪一部分,我很想看看实际代码。

标签: java proxy dynamic-proxy


【解决方案1】:

Java 不允许从代理转换为具体类。 JDK 代理 (java.lang.reflect.Proxy) 只是接口的代理。生成的代理类型为ProxyX(X 是一个数字),如果您尝试将其强制转换为任何类,您将得到ClassCastException

因此,您的第二个和第三个问题不相关 - 代理没有具体类的支持。为此,您可以使用其他代理机制 - CGLIB 或 javassist。它们使用动态子类,因此子类(代理)可以访问所有protected(及以上)字段和方法。

【讨论】:

  • 非常感谢您的快速回复。 Java 不允许强制转换为具体类。
【解决方案2】:

来自 java.lang.reflect.InvocationHandler 的 API javadocs:

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

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

回答您的问题:

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

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

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

// 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;
    }
}

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

【讨论】:

猜你喜欢
  • 2015-10-05
  • 2021-08-27
  • 1970-01-01
  • 2020-04-16
  • 1970-01-01
  • 1970-01-01
  • 2021-02-24
  • 1970-01-01
  • 2013-10-16
相关资源
最近更新 更多