java - 使用 Java-8 时 varargs 中的 ClassCastException
问题描述
以下代码适用于m2()
但ClassCastException
在我使用m1()
.
m1
和之间的唯一区别m2
是参数的数量。
public class Test {
public static void m1() {
m3(m4("1"));
}
public static void m2() {
m3(m4("1"), m4("2"));
}
public static void m3(Object... str) {
for (Object o : str) {
System.out.println(o);
}
}
public static <T> T m4(Object s) {
return (T) s;
}
public static void main(String[] args) {
m1();
}
}
我的问题是 - 当我们使用泛型时,可变参数不能与单个参数一起使用吗?
PS :这与使用泛型和可变参数的 ClassCastException无关
解决方案
让我们跳过您现在忽略未经检查的强制转换警告这一事实,并尝试了解为什么会发生这种情况。
在本声明中:
Test.m3(Test.m4("1"));
有一种推断类型,即 的返回类型m4
。如果要在m3
调用上下文之外使用它,例如:
Test.m4("1"); // T is Object
T
推断为Object
。可以使用类型见证来强制编译器使用给定类型:
Test.<String>m4("1"); // T is String
...或通过在赋值上下文中使用表达式:
String resString = Test.m4("1"); // T is String
Integer resInt = Test.m4("1"); // T is Integer <-- see the problem?
...或在调用上下文中:
Integer.parseInt(Test.m4("1")); // T is String
Long.toString(Test.m4("1")); // T is Long
现在,回到Test.m3(Test.m4("1"));
:我找不到这方面的参考,但我相信编译器被迫T
解析 . 的参数类型m3
,即Object[]
. T
这意味着 必须与的参数类型一致m3
,因此被解析为Object[]
,这就好像您将泛型类型指定为:
Test.m3(Test.<Object[]>m4("1")); // this is what is happening
现在,因为m4
不是返回一个Object[]
,m3
是接收一个String
,这导致了不可避免的ClassCastException
。
如何解决?
解决此问题的第一种方法是为 指定正确的类型参数m4
:
Test.m3(Test.<String>m4("1"));
有了这个,String
是 , 的返回类型m4
,并m3
用单个String
对象(对于Object...
var-arg)调用,就像你写的一样:
String temp = m4("1");
m3(temp);
@Ravindra Ranwala 的已删除答案中建议了第二种方法。在我看来,这归结为注意编译器警告:
public static <T> T m4(Object s) {
return (T) s; // unchecked cast
}
未经检查的强制转换警告只是告诉您编译器(和运行时)不会强制执行类型兼容性,仅仅是因为T
不知道您在哪里强制转换。以下版本是类型安全的,但它也使编译器String
用作 的返回类型m4
以及参数的类型m3
:
public static <T> T m4(T s) {
return s;
}
有了这个,m3(m4("1"));
仍然使用Object...
作为参数类型m3
,同时保持String
返回类型m4
(即字符串值用作Object
数组的第一个元素)。
推荐阅读
- r - 数组没有“dimnames”属性
- c++ - 谁能解释为什么我的合并排序代码不起作用?消费者保护计划;正常进近
- spring-boot - spring boot 数据库切换
- django - 如何将 Vue 添加到 Django?
- clojure - 为什么在这种情况下最后一个功能无法按预期工作
- javascript - React Search 标题结果和 Pagination Material UI
- reactjs - 动画 SVG 组对象 - 使用样式组件进行变换旋转不会围绕圆原点旋转
- javascript - Javascript点击事件在Safari中不起作用,但在其他浏览器中起作用
- dataset - 每个类生成训练数据的场景
- search - 在列表中搜索或在 SharePoint 中使用内容搜索 Webpart 时,文件名以“... default.aspx”结尾的页面不会出现