有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

安卓中的java Outofnowhere ClassCastException

今天早上我醒来发现了一个奇怪的例外:

java.lang.ClassCastException: org.apache.harmony.luni.lang.reflect.ImplForVariable cannot be cast to java.lang.Class

它发生在我尝试获取类型参数类时

例如:

public static Class getTypeParameterClass(Object o, int index) {
    return (Class)
            ((ParameterizedType)o.getClass()
                    .getGenericSuperclass())
                    .getActualTypeArguments()[index];
}

如您所见,此方法获取给定对象类的一个类型参数

它已经工作了几个月了,但今天,它停止了

用法示例:

Collection<Object> foo = new ArrayList<Object>();

Class<?> fooClass = Utils.getTypeParameterClass(foo, 0);

它崩溃了

我是不是因为太多地指责java而受到诅咒

谢谢


共 (2) 个答案

  1. # 1 楼答案

    因此,首先,让我对格雷的耐心表示衷心的感谢

    我终于明白是怎么回事了

    我把注意力集中在了错误的领域

    因此,正如格雷指出的,由于类型擦除,您无法获得编译时未显式给出的类型参数

    我被说服了,错误发生在一个集合字段上,以至于我完全忘记了其他字段

    因此,由于我的数据来自webservices,并且由于JSON映射程序无法直接获取作为root的列表,因此我必须定义包含对象集合、日期(用于缓存)和其他一些与分页相关的内容的模型

    因此,因为编写所有这些类似的类都是胡说八道,所以我尝试概括这个过程,如下所示:

    public abstract class ModelList<T> {
    
            [ paging and caching stuffs ]
    
            @ForeignCollectionField
            Collection<T> collection;
    
            [ constructor, getters, setters ]
    
    }
    

    然后只有子类,如:

    @DatabaseTable(tableName = "category_list")
    public class CategoryList extends ModelList<Category> {
    
    }
    

    因此,我可以拥有更少的详细类,并且可以使用Robospice中的ObjectPersister来概括缓存过程

    我不明白的是(由于缺乏知识),在运行时找不到参数

    更让我困惑的是,我试图复制bug的测试产生了bug!但他们也错了

    因此,请注意赛尔夫(以及其他可能像我一样面临完全胡说八道的人):

    • 不要对语言失去信心(它不是童车,它不是童车,它不是童车…)
    • 不要责备语言(不要太多)
    • 始终将源附加到JAR并设置断点

    最后,解决方案非常简单,只需将集合从ModelList移动到子类,并将getter和setter作为抽象方法保留在ModelList中(对于通用ObjectPersisters)

    我认为这一切都有点太复杂了,如果有人知道使用ormlite/jackson/robospice更好的解决方案,我很高兴听到

  2. # 2 楼答案

    As you can see, this method gets one of the type parameter for a given object's class.

    因此,由于泛型类型擦除,您正在执行的操作是特别不允许的。您正试图调查ArrayList的泛型参数,但当代码运行时,特定的泛型类型不再可见

    如果您处理的是超类,那么您的超类hack(这是一个hack)将起作用。如果您将ArrayList定义为:

    Collection<Object> foo = new ArrayList<Object>() {
        private static final long serialVersionUID = -594043150300376049L;
    };
    

    在这种情况下foo是一个类,扩展了ArraryList。由于某些原因,对于超类,泛型类型参数是可用的