我在StackOverflow上看到了这段注释代码。它会抛出一个Runtime异常。第二部分(未评论的部分)将起作用。我无法找到两者之间的区别,因为两种方法都返回了对象数组。也许我错过了一些基本的理解。你能帮我吗?
public class Safevarargs {
/*
static <Object> Object[] asArray(Object... args) {
return args;
}
static <Object> Object[] arrayOfTwo( Object a, Object b) {
return asArray(a, b);
}
public static void main(String[] args) {
String[] bar = arrayOfTwo("hi", "mom");
}
*/
static <Object> Object[] display(Object... args) {
return args;
}
public static void main(String[] args) {
String[] str = display("hi", "mom");
System.out.print(str[0]);
}
}
答案 0 :(得分:0)
我相信你在施法时遇到了问题。使用部件时
static <Object> Object[] display(Object... args)
编译器实际看到的是
static <Object> Object[] display(Object[]... args)
然后它进一步将其转换为此
static <Object> Object[] display(List[]... args)
这可能允许不应该存在的值
假设您创建一个字符串的对象数组并尝试向其中添加一个int。这会导致不同类型的问题。您可能希望在不使用通用对象的情况下重做它。
或者你也可以使用@SafeVarargs标签。
答案 1 :(得分:0)
这是一个有趣的情况。在第一个例子中,Java抱怨从对象数组转换为字符串数组。
java.lang.ClassCastException:[Ljava.lang.Object;无法转换为[Ljava.lang.String;
在第二种情况下,它处理得很好。问题似乎是类型擦除。当asArray
返回时,它会返回一个基于其参数键入的数组。该信息在arrayOfTwo
的上下文中被删除,其中类型简单地变为Object[]
,并且内容为字符串的事实不再可用。
查看有关类型擦除和不可恢复类型的this post以及对varargs的影响。它确实提供了代码生成的警告的一些上下文,关于&#34;可能的堆污染&#34;:
Safevarargs.java:11:警告:[未选中]参数化vararg类型对象的可能堆污染 static Object [] display(Object ... args){
中声明的java.lang.Object
^ 其中Object是一个类型变量:
Object扩展了方法display(Object ...)
来自文档:
当参数化类型的变量引用不属于该参数化类型的对象时,会发生堆污染。
答案 2 :(得分:0)
要解释这个问题,我们只需要知道java中的泛型如何工作。 编译器在编译过程中在内部使用泛型类型信息,在处理源时生成与类型相关的错误。然后,一旦验证完成,编译器就会生成类型擦除的字节代码,所有对泛型类型的引用都会替换为它们各自的类型擦除。
在你的第二个例子中,它是在编译时编译成字符串。但是在你的第一个例子中,由于asArray是由另一个泛型方法调用的,因此它将在编译期间编译为Object。因此,在运行时,Object []无法转换为String [],这会抛出类转换异常。希望这可以帮到你