字符串数组vs对象数组java

时间:2016-10-06 05:22:05

标签: java types variadic-functions

我在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]);
    }
}

3 个答案:

答案 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){
                                                 ^     其中Object是一个类型变量:
      Object扩展了方法display(Object ...)

中声明的java.lang.Object

来自文档:

  

当参数化类型的变量引用不属于该参数化类型的对象时,会发生堆污染。

答案 2 :(得分:0)

要解释这个问题,我们只需要知道java中的泛型如何工作。 编译器在编译过程中在内部使用泛型类型信息,在处理源时生成与类型相关的错误。然后,一旦验证完成,编译器就会生成类型擦除的字节代码,所有对泛型类型的引用都会替换为它们各自的类型擦除。

在你的第二个例子中,它是在编译时编译成字符串。但是在你的第一个例子中,由于asArray是由另一个泛型方法调用的,因此它将在编译期间编译为Object。因此,在运行时,Object []无法转换为String [],这会抛出类转换异常。希望这可以帮到你