"var" 和原始类型如何组合在一起?

How do "var" and raw types come together?

我遇到了一个 answer 建议使用

var list = new ArrayList();

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

(同时,答案改为使用<String>,但我仍然很好奇但是"principles"这里)

看到了其他的问题比如,但是都是用菱形算子:

var list = new ArrayList<>();

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

I came across an answer that suggests to use...

我会忽略那个答案,因为正如你指出的那样,它使用原始类型 类型 list 作为具体来说 ArrayList(更新:回答者编辑 their answer 以添加元素类型。) 相反:

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>();

但通常我更喜欢编写界面代码而不是具体代码 class,即使是本地人也是如此。也就是说,对于局部变量,它 没有实例成员那么重要,而且 var 很方便。

同时使用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 与 diamond 或泛型方法一起使用时要小心。