【问题标题】:Java raw type declarationJava 原始类型声明
【发布时间】:2017-07-21 07:22:02
【问题描述】:

嗯,这个网站上有很多关于 Java 中的原始类型和泛型的问题。甚至关于为什么下一行代码会出现警告的问题:

List<String> list = new ArrayList();

并且回答了很多次,因为 ArrayList() 是原始类型,因此编译器会发出警告,因为现在 list 不是“类型安全的”,并且编写这行代码的选项仅是为了向后兼容。

我不明白,也没有找到关于它的问题,为什么?由于编译器仅通过“查看”静态引用来编译 Java 代码,为什么编写 new ArrayList(); 而不是 new ArrayList&lt;&gt;(); 的编译时间会有所不同。

比如写这段代码:

List<String> list = new ArrayList(); // 1
list.add("A string"); // 2
list.add(new Object()); // 3

导致第 1 行出现编译警告,第 2 行没有编译问题,但第 3 行出现编译错误 - 类型安全。

因此 - 添加对第一行 (new ArrayList&lt;&gt;();) 的通用引用,只会导致编译器警告的删除。

我知道使用原始类型是一个坏习惯,但我的问题是把右手边写成原始类型有什么区别(编译警告除外)。

谢谢!

【问题讨论】:

    标签: java generics compilation compiler-warnings


    【解决方案1】:

    编译器并不关心你的变量list 所引用的对象是由什么机制创建的。其实也可以参考null。或者它可能是对方法的调用。示例:

    void yourMethod() {
        List<String> list = createStringList();
        ...
    }
    
    List<String> createStringList() {
        return new ArrayList(); // raw type here
    }
    

    当有一个正确的类型化变量(未使用原始类型声明)时,该变量的所有用法都会根据泛型类型进行检查。

    另一件事是,如果您的变量本身是用原始类型声明的:示例:

    List list = new ArrayList();
    list.add("A string");
    list.add(new Object());
    

    这编译得很好,但是警告应该提醒你,因为以后可能会中断!

    【讨论】:

    • 感谢您的回答,以及与null 或使用方法等其他选项的比较。所以我明白 - 从你的回答中的“当有一个适当的......”部分来看,除了烦人的编译警告之外,写 ArrayList(); 而不是 ArrayList&lt;&gt;(); 绝对没有意义和意义? (当然应该避免这种习惯,只是为了一个问题)
    • 嗯...作为一般规则,您应该避免所有警告(尽可能安全)。而且......是的......声明List&lt;String&gt; list = new ArrayList()不会对后面的任何代码造成伤害。
    【解决方案2】:

    假设你有另一个类,其中构造函数参数依赖于类型参数:

    class Foo<T> {
        Foo(T obj) { }
    }
    

    然后编译器会在你用类型参数或者菱形操作符创建参数的时候检查参数类型:

     Foo<String> bar = new Foo<>(42); // doesn't compile
    

    但是原始类型会关闭泛型检查:

     Foo<String> bar = new Foo(42); // does compile but causes heap pollution
    

    所以警告是必要的。

    【讨论】:

    • 很好的例子!谢谢
    猜你喜欢
    • 1970-01-01
    • 2018-10-26
    • 2018-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-20
    • 1970-01-01
    相关资源
    最近更新 更多