"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
很方便。
同时使用var
和diamond
是合法的,但是推断的类型会改变:
var list = new ArrayList<>(); // DANGEROUS: infers as ArrayList<Object>
为了进行推断,diamond
可以使用目标类型(通常是声明的左侧)或构造函数参数的类型。如果两者都不存在,它会退回到最广泛的适用类型,通常是 Object
1.
对于 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
结论:
- 无论
var
是否存在,都不要使用原始类型。
- 确保方法或构造函数参数提供足够的类型信息,以便推断的类型符合您的意图。否则,避免同时使用
var
和 diamond
1.
1 - Style Guidelines 用于局部变量类型推断:G6。将 var 与 diamond 或泛型方法一起使用时要小心。
我遇到了一个 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
很方便。
同时使用var
和diamond
是合法的,但是推断的类型会改变:
var list = new ArrayList<>(); // DANGEROUS: infers as ArrayList<Object>
为了进行推断,diamond
可以使用目标类型(通常是声明的左侧)或构造函数参数的类型。如果两者都不存在,它会退回到最广泛的适用类型,通常是 Object
1.
对于 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
结论:
- 无论
var
是否存在,都不要使用原始类型。 - 确保方法或构造函数参数提供足够的类型信息,以便推断的类型符合您的意图。否则,避免同时使用
var
和diamond
1.
1 - Style Guidelines 用于局部变量类型推断:G6。将 var 与 diamond 或泛型方法一起使用时要小心。