将Object强制转换为ArrayList<String[]>时出现“警告:[unchecked]未经检查的转换”。

7

奇怪的情况-以下是代码:

ArrayList<String[]> listArr = new ArrayList<>();
Object[] obj = new Object[]{"str", listArr};

String str = (String) obj[0];//OK
ArrayList<String[]> list = (ArrayList<String[]>) obj[1];//warning: [unchecked] unchecked cast

当使用编译器选项-Xlint:unchecked构建项目时,在项目属性中,我会收到一个警告:

警告:[unchecked] 未经检查的转换
                 ArrayList list =(ArrayList)obj [1];
必需:ArrayList
找到: Object

但是以同样的方式将String转换是可以的。这里的问题是什么?
3个回答

6

这是因为编译器无法在列表级别验证内部类型,所以您需要先验证列表和内部类型。

而不是 ArrayList<String[]> list = (ArrayList<String[]>) obj[1];

应该是 ArrayList<?> list = (ArrayList<?>) obj[1];


1
好的,但是以后如何将它更改为ArrayList<String[]>类型,这样我就可以将其传递给需要ArrayList<String[]>的方法(否则代码将无法编译)?还是我应该忽略这个警告? - Ernestas Gruodis
1
@Ernestas Gruodis:这是一种限制,如果不对Java语言和JVM进行深入、不兼容的更改,无法解决。但问题是为什么您要使用Object[]?Java的类型系统允许您跟踪对象的类型,如果您故意决定删除这些类型信息,就不应该抱怨丢失了类型信息... - Holger
Object[] 因为该方法返回多种数据类型。这意味着问题已经得到解答。 - Ernestas Gruodis
在我的情况下,我必须使用 ObjectInputStream 的 readObject() 方法,因此默认情况下返回的是一个 Object... 因此将其更改为我需要的正确类型的对象是棘手的。 - Azurespot

2
这是因为如果你试图将整数转换为字符串,你会在运行时得到ClassCastException异常。但在这里不会出现ClassCastException异常:
    ArrayList<Integer[]> listArr = new ArrayList<>();
    ArrayList<String[]> list = (ArrayList<String[]>) obj[1];

是的,你确实这样做了,但运行时无法知道,因此它会警告你无法强制执行转换的泛型类型参数。 - eckes
我相信 ArrayList<Integer[]> 是一种具体类型的泛型。为了避免上述问题,必须使用 ArrayList<?> - IgorGanapolsky
嘿!我有两个问题关于你的回答:如果在你的例子中没有抛出ClassCastException,那么实际上会发生什么?未定义的行为?随机值?其次:这是否意味着编写自己的包装器类来处理ArrayList<String>(或者无论您想要的集合是什么)是解决问题的有效方法?我的意思是,如果我有像MyStringList这样的东西,它在内部将存储一个ArrayList<String>,那么它再次可能会在运行时抛出classCastException - 这是解决问题的合法方法吗? - dingalapadum
重新思考:这种推理正确吗:强制转换将不会引发ClassCastException,但是稍后当我们尝试对其中一个元素执行某些操作时(该元素不会是适当的类型),我们实际上会得到ClassCastException,对吗? - dingalapadum

2
编译器报错了。
ArrayList<String[]> list = (ArrayList<String[]>) obj[1]

因为类型转换是在运行时检查的,所以在运行时,你的ArrayList<String[]> 可能会成为一个ArrayList<Whatever[]>,因为obj的类型是未知的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接