代理创建时的 java.lang.ClassCastException

阿里·塔哈

我的目标是从class实现 aninterface并扩展另一个class.

...实体注释:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface Entity {

    String visibileName();

}

...实现IEventDesignDialog

      public class EventDesignDialog implements IEventDesignDialog{

        private String show;
        private String dateAndTimeDisplayFormat;
        private String eventType;


        @Entity(visibileName = "Show")
        public String getShow() {
            return this.show;
        }

        @Entity(visibileName = "Date And Time display format")
        public String getDateAndTimeDisplayFormat() {
            return this.dateAndTimeDisplayFormat;
        }

        @Entity(visibileName = "Event Type")
        public String getEventType() {
            System.out.println("get event type method invokde successfully");
            return this.eventType;
        }
}

IEventDesignDialog 界面:

public interface IEventDesignDialog extends IPage{

    public String getShow();

    public String getDateAndTimeDisplayFormat();

    public String getEventType();


}

IPage 界面:

public interface IPage {

}

动态代理实现:

public class IPageProxy implements InvocationHandler {
    private List<Method> entityMethods;



    private Class <? extends IPage> screenClazz;

    public IPageProxy(final Class <? extends IPage> screenClazz) {
        entityMethods = new ArrayList<>();
        getEntityAnnotatedMethods(screenClazz);
        // Accept the real implementation to be proxied
        this.screenClazz = screenClazz;
    }


    /**
     * create an page instance
     * @param type
     * @param
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static IPage getInstance(final Class<? extends IPage> type)
            throws InstantiationException, IllegalAccessException {

        List<Class<?>> interfaces = new ArrayList<>();
        interfaces.addAll(Arrays.asList(type.getInterfaces()));

        return (IPage) Proxy.newProxyInstance(
                type.getClassLoader(),
                findInterfaces(type),
                new IPageProxy(type)
             );

        /*return (IPage) Proxy.newProxyInstance(type.getClassLoader(),
               interfaces.toArray(new Class<?>[interfaces.size()])
                , new IPageProxy(type));*/
    }


    /**
     * get all methods that annotated with @Entity annotation
     * and add it for entityMethods array List
     * @param screenClazz
     */
    private void getEntityAnnotatedMethods(final Class <? extends IPage>  screenClazz) {
        // Scan each interface method for the specific annotation
        // and save each compatible method
        for (final Method m : screenClazz.getDeclaredMethods()) {
            if (m.isAnnotationPresent(Entity.class)) {
                entityMethods.add(m);
            }
        }
    }


    static Class<?>[] findInterfaces(final Class<? extends IPage> type) {
        Class<?> current = type;

        do {
            final Class<?>[] interfaces = current.getInterfaces();

            if (interfaces.length != 0) {
                return interfaces;
            }
        } while ((current = current.getSuperclass()) != Object.class);

        throw new UnsupportedOperationException("The type does not implement any interface");
    }



    @Override
    public Object invoke(
            final Object proxy,
            final Method method,
            final Object[] args) throws InvocationTargetException, IllegalAccessException {
        // A method on MyInterface has been called!
        // Check if we need to go call it directly or if we need to
        // execute something else before!


        if (entityMethods.contains(method)) {
            // The method exist in our to-be-proxied list
            // Execute something and the call it
            // ... some other things
            System.out.println("Something else");
        }

        // Invoke original method
        return method.invoke(screenClazz, args);
    }

}

主要类:

public class Main {

    public static void main(String[] args) {
        try {

            ((EventDesignDialog)getInstance(EventDesignDialog.class)).getEventType();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }


    @SuppressWarnings("unchecked")
    public static <T extends IPage> T getInstance(final Class<? extends IPage> type) throws InstantiationException, IllegalAccessException {
        return (T) IPageProxy.getInstance(type);
    }

}

抛出以下异常:

  Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy2 cannot be cast to abc.EventDesignDialog
    at abc.Main.main(Main.java:8)
LppEdd

您正在扩展 Screen,这意味着它不是interface.
动态代理仅interface在层次结构中存在基础时才起作用

interfaces.size() == 0

因此代理不能实现 any interface,显然它不是Screen层次结构的一部分


如果Screeninterface,则您的方法仍然太复杂。

public static Screen getInstance(Class<? extends Screen> type)

足够了。


您仍然会收到异常,因为

Class#getInterfaces

返回由此interface实现s

这意味着如果您在 on 上调用它EventDesignDialog.class,它将返回一个空数组。
这意味着如果您在 上调用它EntityDesignDialog.class,它仍然会返回一个空数组。
在调用它时Screen.class,它会返回

[IPage.class]

你需要循环层次结构

Class#getSuperclass

直到找到合适的interface

一个可能的实现可能看起来像

static Class<?>[] findInterfaces(final Class<?> type) {
    Class<?> current = type;

    do {
        final Class<?>[] interfaces = current.getInterfaces();

        if (interfaces.length != 0) {
            return interfaces;
        }
    } while ((current = current.getSuperclass()) != Object.class);

    throw new UnsupportedOperationException("The type does not implement any interface");
}

这意味着您需要将代码更改为

return (IPage) Proxy.newProxyInstance(
              type.getClassLoader(),
              findInterfaces(type),
              new IPageProxy(type)
           );

但是,由于您已经知道结果将是IPage代理,因此您可以

return (IPage) Proxy.newProxyInstance(
              type.getClassLoader(),
              new Class[] { IPage.class },
              new IPageProxy(type)
           );

这里

public static IPage getInstance(final Class<? extends IPage> type)

你要返回一个IPage,但在这里

((EventDesignDialog)getInstance(EventDesignDialog.class))

您正在尝试对其进行向下转换,这意味着您正在尝试将其转换为更具体的类型。这是不可能的,因为 Proxy 不是 type EventDesignDialog,但它只是实现了您的IPage接口。

由于动态代理是基于接口的,您将被迫处理接口。
尝试转换为具体类将始终抛出异常。

如果您需要IEventDesignDialog,则需要专门为它创建一个新的代理。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

java.lang.ClassCastException:创建同步的链表

java.lang.ClassCastException

java.lang.ClassCastException关于在Java中创建类的数组

java.lang.ClassCastException:转换为创建的接口问题?

从SOAPFault提取错误消息时出现java.lang.ClassCastException

从SuperClass转换子类时发生异常java.lang.classCastException

Hibernate:保存时为java.lang.ClassCastException

java.lang.LinkageError:ClassCastException

获取 java.lang.ClassCastException

java.lang.ClassCastException:错误

Java.lang.reflect.Proxy从调用返回另一个代理导致分配时ClassCastException

java.lang.ClassCastException: java.lang.String 在实现 Parcelable 时不能被强制转换

创建RDD [LabeledPoint]:java.lang.ClassCastException:无法将java.lang.Long强制转换为java.lang.Double

java.lang.ClassCastException:使用Univocity时无法将java.util.Date强制转换为java.lang.String

Spring with Querydsl :java.lang.ClassCastException

运行时java.lang.ClassCastException

java.lang.ClassCastException-Log4j

Jsf错误:java.lang.ClassCastException

java.lang.ClassCastException.如何删除?

Collection.toArray()java.lang.ClassCastException

某些设备上的 java.lang.ClassCastException

randomSplit 期间的 scala java.lang.ClassCastException

当我将内容从文件投射到对象时,java抛出java.lang.ClassCastException

访问用Java编写的Web服务方法时发生java.lang.ClassCastException。杰克斯

获取Shared Preference值时,不能将ClassCastException java.lang.Integer强制转换为java.lang.Long

Restcomm 无法分配和创建 sbb 对象 java.lang.ClassCastException

使用java.lang.Double值时,组合器中的验证器将引发ClassCastException

在休眠4中使用Projection时java.lang.ClassCastException

处理Sys refcursor时如何解决java.lang.ClassCastException?