“var”和原始类型如何结合使用?

17

我看到了一个answer,建议使用

var list = new ArrayList();

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

(同时,答案已更改为使用<String>,但我仍然对这里的“原则”感到好奇)

我看到其他类似this的问题,但它们都使用了钻石操作符:

var list = new ArrayList<>();

现在,我只是想知道:使用var是否改变了我们对于原始类型的使用方式?或者说忽略<>是一个不好的做法建议?

5
你好,FYI,你在第一句中提供的链接 the answer 被作者编辑以添加 <String> - T.J. Crowder
2
@SudhirOjha 同样的问题问你:在那个问题中,哪里有任何关于在var与原始类型一起使用的讨论? - GhostCat
2
不错的问题。我猜Brian的这篇文章Stuart的另一篇文章可能是很好的阅读材料,可以更好地了解风格和风险。Holger也指出原始类型,我猜他看到这样的问题在某个时候会出现。 - Naman
6
很简单。对于使用var声明的局部变量,我们将 RHS 的类型作为独立表达式进行计算(然后执行一种称为“向上投影”的过程来消除捕获变量)。如果 RHS 是原始类型,则推断出的类型也是原始类型。没有任何魔法。 - Brian Goetz
@SudhirOjha 我不认为这是我的问题的重复,因为我的问题实际上并没有涉及原始类型。 - Jacob G.
2个回答

31
我看到一篇答案建议使用...。我会忽略那个答案,因为正如你指出的那样,它使用了原始类型和将list具体化为ArrayList。相反,回答者编辑了他们的答案以添加元素类型。
List<AppropriateElementType> list = new ArrayList<>();

根据您提供的第二个链接中的答案,如果您包含<>var将会导致编译器从右侧推断出元素类型,并选择最具体的类型。在var list = new ArrayList<>();中,这将是ArrayList<Object>,因为它没有更具体的类型可选。
但是,下面这段代码:
var list = new ArrayList();

...没有使用<>,而是使用了原始类型(ArrayList),没有使用参数化类型,参数应该是Object (ArrayList<Object>),这是不同的。


如果使用list的范围足够小(在一个方法中只有几行),那么将其类型定义为ArrayList<X>而不是List<X>可能是可以接受的(取决于您的编码风格),在这种情况下:

var list = new ArrayList<AppropriateElementType>();

但通常我更喜欢编写针对接口而不是具体类的代码,即使是在局部变量中也是如此。话虽如此,在局部变量中,这比实例成员更不重要,而var很方便。


3
作为原问题的回答者,我想指出这只是一个随意提到在原回答中var表达式看起来的方式,并且我忘记将类型信息从左侧移动到右侧(被var替换了)。在我注意到这一点并有机会修复之前,这个问题就被提出了。 - Thorbjørn Ravn Andersen

10

使用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 - 本地变量类型推断的风格指南: G6. 在使用带有菱形语法(diamond)或泛型方法时要小心使用var。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接