“var”和原始类型是如何结合在一起的?

2022-09-02 23:37:29

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

var list = new ArrayList();

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

(同时,答案被改成了使用,但我仍然很好奇,但这里的“原则”)<String>

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

var list = new ArrayList<>();

现在我只是想知道:是否应该改变我们应该(不)使用原始类型的方式?还是说,这种建议只是简单地省略了不好的做法?var<>


答案 1

我遇到了一个建议使用...

我会忽略这个答案,因为正如你所指出的,它使用原始类型,并且它专门类型。(更新:回答者编辑了他们的答案以添加元素类型。相反:listArrayList

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

根据您链接的第二个答案,如果您包含 ,会导致编译器从右侧推断出元素类型,从而选择它所能获得的最具体的类型。不过,因为没有任何更具体的东西可以选择。var<>var list = new ArrayList<>();ArrayList<Object>

但是,这个:

var list = new ArrayList();

...不带 ,则使用原始类型 (),而不是参数化类型 (),这是不同的。<>ArrayListObjectArrayList<Object>


如果使用足够包含(方法中的几行),则将其键入而不是键入可能是可以接受的(取决于您的编码风格),在这种情况下:listArrayList<X>List<X>

var list = new ArrayList<AppropriateElementType>();

但一般来说,我更喜欢在接口上编码,而不是具体类,即使对于局部变量也是如此。也就是说,对于本地人来说,它不如实例成员重要,而且很方便。var


答案 2

同时使用 和 是合法的,但推断的类型将更改:vardiamond

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

对于其推理,可以使用目标类型(通常为声明的左侧)或构造函数参数的类型。如果两者都不存在,则回退到最广泛的适用类型,通常为 1diamondObject

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

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. 确保方法或构造函数参数提供足够的类型信息,以便推断出的类型与您的意图相匹配。否则,请避免将两者都与 1 一起使用vardiamond

1 - 局部变量类型推断的样式指南:G6。将 var 与金刚石或通用方法一起使用时要小心。