【问题标题】:Java Generics Cast ErrorJava 泛型转换错误
【发布时间】:2012-05-22 16:33:45
【问题描述】:

对应标题,我的问题是获取一个泛型数组的array-length,它在一个类的实例内部,已经用这个泛型类型进行了初始化。 当我想获取我的数组的长度(ak.array.length)时,java 会抛出这个错误:

线程“main”中的异常 java.lang.ClassCastException: [Ljava.lang.Object;不能转换为 [Ljava.lang.String; 在 Testclass.main(Testclass.java:15)

那么我在这段代码中的错在哪里? 提前致谢

public class Testclass {

    static class ArrayKeeper<T> {
        protected T[] array;

        public ArrayKeeper() {
            array = (T[])new Object[5];
        }
    }

    public static void main(String[] args) {
        //create a new instance of inner class ArrayKepper (type String)
        Testclass.ArrayKeeper<String> ak = new Testclass.ArrayKeeper<String>();
        System.out.println(ak.array.length); //cast error here.
    }
}

【问题讨论】:

    标签: java generics classcastexception


    【解决方案1】:

    问题出在这一行:

    array = (T[]) new Object[5];
    

    这不是创建通用数组的方法,您创建的是Object[],而不是您想要的String[]。您不能创建 Object[] 然后将其转换为您想要的任何类型,您必须创建正确类的数组。试试这个:

    public ArrayKeeper(Class<T> clazz, int size) {
        array = (T[]) Array.newInstance(clazz, size);
    }
    

    然后,当您需要实例化 ArrayKeeper 时,请执行以下操作:

    Testclass.ArrayKeeper<String> ak =
        new Testclass.ArrayKeeper<String>(String.class, 5);
    

    【讨论】:

    • 嗯。比基于反射的方法更好的是使用 API 隐藏强制转换。看看例如ArrayList 在 Java 中的实现:它由一个普通的旧 Object[] 支持,并且对象在调用 get(int) 等时被强制转换。只要避免暴露演员表,你就会被设置。
    • 反射很慢,需要您绕过并跟踪大量完全冗余的Class 对象。最好的选择可能是使用 List 而不是数组,但如果做不到这一点,通过传递 Class 对象来弄乱你的 API 实在是太尴尬了。
    • @LouisWasserman 反射没有像以前那么慢(这是一个常见的误解),此外,如果你这样做,你怎么知道这是否会变慢不知道预期用途,尚未对其进行分析? W.r.t.传递 Class 对象,这是一个非常常见的习惯用法,在 Java 的 API 本身中到处都在使用。
    • Java API 的哪些部分?在集合框架中没有任何地方,尽管 EnumMapEnumSet 有一个值得注意的(和值得的)例外。我会......承认反射比以前快得多,我相信Array.newInstance 习惯用法实际上最终会在AbstractCollection.toArray(T[]) 中使用。但是……如果你坚持,这里有另一个论点:如果T 本身是一个泛型类型怎么办?您在此答案中描述的方法阻止您使用通用 T
    • @LouisWasserman 请先阅读FAQ
    【解决方案2】:

    我认为您需要在ArrayKeeper 中实现length getter,因为您不能将Object[] 转换为String[],而调用ak.array 确实会尝试执行该转换。

    【讨论】:

    • 据我了解:数组不 = (T[])new Object[5];已经进行演员表了吗?
    • 不。由于运行时的类型擦除,此时没有发生实际的转换。 (类型擦除后,T 变为 Object。)
    猜你喜欢
    • 2013-05-14
    • 2019-07-14
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    相关资源
    最近更新 更多