仿制,数组和所述ClassCastException异常 [英] Generics, arrays, and the ClassCastException

查看:303
本文介绍了仿制,数组和所述ClassCastException异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我觉得一定有什么微妙的事情在这里,我不知道。考虑以下几点:

 公共类Foo< T> {
  私人T [] A =(T [])新对象[5];  公共美孚(){
    //添加一些元素,以一个
  }  大众T []木屐(){
    返回;
  }
}

假设你的主要方法包含以下内容:

 美孚<双> F =新的Foo<双>();
双[] D = f.getA();

您会得到一个CastClassException与消息的java.lang.Object不能转换为java.lang.Double中。

谁能告诉我为什么吗?我抛出ClassCastException的理解是,当你试图对象转换无法铸造一种被抛出。也就是说,子类,它是不是一个实例(引用文档)。例如:

 对象o =新的双(3);
双D =(双人间)O; //投工作
字符串s =(字符串)O; // ClassCastException异常

和它似乎我能做到这一点。如果 A 只是一个 T 而不是数组 T [] ,我们可以得到 A 并投它没有问题。阵列为什么要打破这个?

感谢。


解决方案

 美孚<双> F =新的Foo<双>();

当您使用该版本的通用类Foo,那么对于成员变量 A ,编译器基本上采取这一行:

 私人T [] A =(T [])新对象[5];

双替换 T 来得到这样的:

 私人双[] A =(双人间[])新对象[5];

您不能从Object转换为双,因此ClassCastException异常。

更新和澄清:其实,在运行一些测试code之后,抛出ClassCastException比这更微妙。例如,这主要方法将正常工作没有任何异常:

 公共静态无效的主要(字串[] args){
美孚<双> F =新的Foo<双>();
的System.out.println(f.getA());
}

当您尝试分配时发生该问题 f.getA()来类型的引用双击[]

 公共静态无效的主要(字串[] args){
美孚<双> F =新的Foo<双>();
双[] A2 = f.getA(); //抛出ClassCastException异常
的System.out.println(A2);
}

这是因为有关成员变量 A 在运行时擦除的类型信息。泛型只提供类型安全的编译时间的(我以某种方式在我最初的帖子忽略这一点)。所以,问题不在于

 私人T [] A =(T [])新对象[5];

由于在运行时该code是真的

 私有对象[] =一个新的对象[5];

将出现问题时方法的结果木屐(),它在运行时实际返回的对象[] ,被分配到类型的引用双击[] - 这句话引发ClassCastException异常,因为对象不能被转换为双

更新2 :回答你的最后一个问题为什么阵列打破这个?答案是因为语言规范不支持通用阵列。 看到这个论坛的帖子更多 - 为了向后兼容,没有人知道关于T的类型在运行时。

I think there must be something subtle going on here that I don't know about. Consider the following:

public class Foo<T> {
  private T[] a = (T[]) new Object[5];

  public Foo() {
    // Add some elements to a
  }

  public T[] getA() {
    return a;
  }
}

Suppose that your main method contains the following:

Foo<Double> f = new Foo<Double>();
Double[] d = f.getA();

You will get a CastClassException with the message java.lang.Object cannot be cast to java.lang.Double.

Can anyone tell me why? My understanding of ClassCastException is that it is thrown when you try to cast an object to a type that cannot be casted. That is, to a subclass of which it is not an instance (to quote the documentation). e.g.:

Object o = new Double(3.);
Double d = (Double) o; // Working cast
String s = (String) o; // ClassCastException

And it seems I can do this. If a was just a T instead of an array T[], we can get a and cast it without a problem. Why do arrays break this?

Thanks.

解决方案

Foo<Double> f = new Foo<Double>();

When you use this version of the generic class Foo, then for the member variable a, the compiler is essentially taking this line:

private T[] a = (T[]) new Object[5];

and replacing T with Double to get this:

private Double[] a = (Double[]) new Object[5];

You cannot cast from Object to Double, hence the ClassCastException.

Update and Clarification: Actually, after running some test code, the ClassCastException is more subtle than this. For example, this main method will work fine without any exception:

public static void main(String[] args) {
	Foo<Double> f = new Foo<Double>();
	System.out.println(f.getA());
}

The problem occurs when you attempt to assign f.getA() to a reference of type Double[]:

public static void main(String[] args) {
	Foo<Double> f = new Foo<Double>();
	Double[] a2 = f.getA(); // throws ClassCastException
	System.out.println(a2);
}

This is because the type-information about the member variable a is erased at runtime. Generics only provide type-safety at compile-time (I was somehow ignoring this in my initial post). So the problem is not

private T[] a = (T[]) new Object[5];

because at run-time this code is really

private Object[] a = new Object[5];

The problem occurs when the result of method getA(), which at runtime actually returns an Object[], is assigned to a reference of type Double[] - this statement throws the ClassCastException because Object cannot be cast to Double.

Update 2: to answer your final question "why do arrays break this?" The answer is because the language specification does not support generic array creation. See this forum post for more - in order to be backwards compatible, nothing is known about the type of T at runtime.

这篇关于仿制,数组和所述ClassCastException异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆