我的问题涉及使用动态代理和Java泛型进行类型转换的行为。更具体地说,我想使用动态代理来检测一个servelet对象。为了获得更好的可重用性,我采用了一些通用代码模板来创建代理对象,如下所示。

@SuppressWarnings("unchecked")
public static <T> T instrument(final T aT) {
    T proxy = (T) Proxy.newProxyInstance(aT.getClass().getClassLoader(), new Class[]{MyServelet.class}, new InvocationHandler() {
        @Override
        public Object invoke(Object aProxy, Method aMethod, Object[] aArgs) throws Throwable {
        ..... instrumentation logic goes here
        }
    });
     System.out.println("proxy class " + proxy.getClass());
     System.out.println("input class " + aT.getClass());
     return proxy;
}


这里的T是我的具体的Servelet实现类,它实现了MyServelet接口。但是,如果我运行上述方法,它将打印出

proxy class class com.sun.proxy.$Proxy0
input class class MyServeletImplementation


所以我想知道代码片段中的类型转换语句发生了什么。由于代理没有被强制转换为MyServeletImplementation,所以它似乎悄然失败了,但是它也没有抛出ClassCastException。有人可以让我对此有所了解吗?谢谢!

最佳答案

由于type erasure,在该方法的实际编译字节码中未进行任何强制转换。

生成字节码时,编译器会将参数类型的任何变量视为与该参数类型的上限具有相同类型的变量;如果类型不受限制,则将其视为Object。因此,如果方法中的T具有约束<T extends MyServelet>,则编译器会将proxy视为类型为MyServelet的变量,并插入了强制类型转换。但是,由于T是无界的,因此将其视为Object类型的变量-因此,不进行强制转换。

09-25 23:03
查看更多