【问题标题】:How do "var" and raw types come together?“var”和原始类型如何结合在一起?
【发布时间】:2019-01-13 07:42:24
【问题描述】:

我遇到了一个建议使用的answer

var list = new ArrayList();

我很惊讶在这里发现了一个原始类型,我只是想知道:var 是否自动使用<>“?

(同时答案改用<String>,不过我还是好奇不过这里的“原理”)

看到this之类的其他问题,都用菱形运算符:

var list = new ArrayList<>();

现在我只是想知道:var 是否改变了我们应该(不)使用原始类型的方式?还是说忽略&lt;&gt; 的建议只是不好的做法?

【问题讨论】:

  • 仅供参考,the answer 您在第一句话中链接的内容已被作者编辑添加为&lt;String&gt;
  • @SudhirOjha 你也有同样的问题:在那个问题中,any 讨论了关于将原始类型与 var 结合使用的讨论?
  • 好问题。我想this article by Briananother one by Stuart 可能是更好地了解风格和风险的好书。 Holger 是pointing to the raw types as well,我猜,他看到了这样一个问题。
  • 这很简单。对于 var 声明的本地变量,我们将 RHS 的类型计算为独立表达式(然后执行称为 upward projection 的过程来投影捕获变量。)如果 RHS 是原始的,则推断的类型是原始类型。没有魔法。
  • @SudhirOjha 我不认为这是我的问题的重复,因为我的问题根本不涉及原始类型。

标签: java generics var local-variables java-10


【解决方案1】:

我遇到了一个建议使用的答案...

我会忽略这个答案,因为正如您所指出的,它使用原始类型并且它将list 类型具体为ArrayList(更新:回答者编辑 their answer 以添加元素类型。) 改为:

List<AppropriateElementType> list = new ArrayList<>();

根据second answer you linked,如果您包含&lt;&gt;var 导致编译器从右侧推断元素类型,选择最具体的类型.不过,在 var list = new ArrayList&lt;&gt;(); 中应该是 ArrayList&lt;Object&gt;,因为它没有任何更具体的内容可供选择。

但是,这个:

var list = new ArrayList();

...没有&lt;&gt;,使用的是原始类型(ArrayList),而不是带有Object作为参数的参数化类型(ArrayList&lt;Object&gt;),这是不同的。


如果list 的使用被充分包含(一个方法中的几行),则将其键入ArrayList&lt;X&gt; 而不是List&lt;X&gt; 可能是可以接受的(取决于您的编码风格),在这种情况下:

var list = new ArrayList<AppropriateElementType>();

但通常我更喜欢编写接口而不是具体类,即使是本地人也是如此。也就是说,对于本地人来说,它没有实例成员那么重要,而且var 很方便。

【讨论】:

  • 作为原始问题的回答者,我只想指出,这是对 var 表达式在原始答案上下文中的外观的临时参考,我忘记移动从左侧(已被 var 替换)到右侧键入信息。在我注意到有人对此发表评论并有机会修复它之前,有人问了这个问题。
【解决方案2】:

vardiamond同时使用是合法的,但是推断的类型会改变:

var list = new ArrayList<>(); // DANGEROUS: infers as ArrayList<Object>

为了推断,diamond 可以使用目标类型(通常是声明的左侧)或构造函数参数的类型。如果两者都不存在,则回退到最广泛的适用类型,通常是Object1

使用diamond 和泛型方法,可以通过实际参数向构造函数或方法提供额外的类型信息,从而可以推断出预期的类型1

var list = List.of(BigInteger.ZERO); // OK: infers as List<BigInteger>
var list = new ArrayList<String>( ); // OK: infers as ArrayList<String>

鉴于以上情况,我不建议做以下事情(因为你会得到原始的ArrayList类型):

var list = new ArrayList(); // DANGEROUS: infers as ArrayList

结论:

  1. 无论var 是否存在,都不要使用原始类型。
  2. 确保方法或构造函数参数提供足够的类型信息,以便推断的类型与您的意图相匹配。否则,请避免同时使用 vardiamond1

1 - Style Guidelines 用于局部变量类型推断:G6。将 var 与菱形或泛型方法一起使用时要小心。

【讨论】:

    猜你喜欢
    • 2018-03-02
    • 1970-01-01
    • 2013-06-18
    • 2010-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多