4

嗨检查下面的代码

   ArrayList x=new ArrayList();
   ArrayList<String>y=x;
   ArrayList<StringBuffer>z=x;
   y.add("Strings");
   System.out.println(z.get(0).toString());

我在 System.out.println 收到 Class Cast 异常

 java.lang.ClassCastException: java.lang.String
 at com.one.MainClass.main(MainClass.java:16)

但是当我尝试

  System.out.println(z.get(0)) 

它正在工作为什么会这样?

4

2 回答 2

2

我假设您这样做是作为一个实验(如果不是,那么请阅读其他答案,了解您应该如何编写代码)。

x 是一个 raw ArrayList,您可以在其中放置任何类型的对象。

y.add("string")添加一个字符串。

z 是一个ArrayList<StringBuffer>并且需要 StringBuffers。当您调用z.get(0)时,JVM 会在返回之前尝试将索引 0 处的元素转换为 StringBuffer。那个演员失败了。

换句话说,虽然StringBuffer s = z.get(0);可以编译,但它会在运行时抛出 ClassCastException,因为z.get(0)它不是StringBuffer.

于 2012-08-05T15:49:00.017 回答
1

关于您遇到问题的具体原因如下:

  • 新的 ArrayList 已创建,为空
  • 所有元素都输入到 String in y
  • 所有元素都输入到 z 中的 StringBuffer
  • 一个新元素被添加到这个数组列表中。
  • JVM 尝试将其转换为 String 和 StringBuffer
  • 因为“Strings”不是 StringBuffer 的实例,所以抛出 ClassCastException。

为避免这种情况,不要将数组类型化为 String 和 StringBuffer。只选择一个。例如:

ArrayList<StringBuffer> myArrayList = new ArrayList<StringBuffer>

如果要将 String 数组列表复制到 StringBuffer ArrayList 中,则必须遍历 z 中的所有项目以将它们转换为字符串缓冲区:

ArrayList x=new ArrayList();
ArrayList<String>y=x;
ArrayList<StringBuffer>z=new ArrayList<StringBuffer>();
for(String s : y)
    z.add(new StringBuffer(s));

原因是 StringBuffer 不扩展 String。导致问题的原因是您不能将字符串转换为字符串,例如对 StringBuffer 说“str”,即您不能这样做StringBuffer s = (StringBuffer)"str";

ArrayList x转换为ArrayList<T>, 的所有元素都x必须是扩展的或者是 的实例T

此外,如果可能,您应该始终使用泛型类型。如果您不知道列表中的内容(例如),请使用:

ArrayList<?> x = new ArrayList<?>();

如果您知道更多,例如它将是另一个类的子类,请使用 ArrayList<? extends T>or ArrayList<? implements T>。这将帮助您避免未来的 ClassCastExceptions。

于 2012-08-05T15:43:07.530 回答