Jok*_*ker 5 java generics exception java-8
以下代码工作正常,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();
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是 - 当我们使用泛型时,varargs 是否不适用于单个参数?
ern*_*t_k 10
让我们暂时跳过您忽略未经检查的强制转换警告这一事实,并尝试了解为什么会发生这种情况。
在此声明中:
Test.m3(Test.m4("1"));
Run Code Online (Sandbox Code Playgroud)
有一种推断类型,即 的返回类型m4。如果要在m3调用上下文之外使用它,例如:
Test.m4("1"); // T is Object
Run Code Online (Sandbox Code Playgroud)
T推断为Object。可以使用类型见证来强制编译器使用给定类型:
Test.<String>m4("1"); // T is String
Run Code Online (Sandbox Code Playgroud)
...或通过在赋值上下文中使用表达式:
String resString = Test.m4("1"); // T is String
Integer resInt = Test.m4("1"); // T is Integer <-- see the problem?
Run Code Online (Sandbox Code Playgroud)
...或在调用上下文中:
Integer.parseInt(Test.m4("1")); // T is String
Long.toString(Test.m4("1")); // T is Long
Run Code Online (Sandbox Code Playgroud)
现在,回到Test.m3(Test.m4("1"));:我找不到对此的引用,但我相信编译器被迫T解析 的参数类型m3,即Object[]. 这意味着T,它必须与参数类型一致m3,因此,决心Object[],并就好像您指定的通用类型,这使得它:
Test.m3(Test.<Object[]>m4("1")); // this is what is happening
Run Code Online (Sandbox Code Playgroud)
现在,因为m4不是返回 an Object[],m3而是接收 a String,这导致了不可避免的ClassCastException.
解决此问题的第一种方法是为 指定正确的类型参数m4:
Test.m3(Test.<String>m4("1"));
Run Code Online (Sandbox Code Playgroud)
有了这个,String是 的返回类型m4,并m3使用单个String对象(对于Object...var-arg)调用,就像您编写的一样:
String temp = m4("1");
m3(temp);
Run Code Online (Sandbox Code Playgroud)
@Ravindra Ranwala 删除的答案中建议了第二种方法。在我看来,这归结为注意编译器警告:
public static <T> T m4(Object s) {
return (T) s; // unchecked cast
}
Run Code Online (Sandbox Code Playgroud)
在未检查铸警告只是告诉你,编译器(和运行时)不打算强制类型兼容性,仅仅是因为T不知道,你投。以下版本是类型安全的,但它也使编译器String用作 的返回类型m4以及参数的类型m3:
public static <T> T m4(T s) {
return s;
}
Run Code Online (Sandbox Code Playgroud)
这样,m3(m4("1"));仍然Object...用作 的参数类型m3,同时保持String返回类型 的m4(即,字符串值用作Object数组的第一个元素)。