Java中典型的ArrayList
声明属于以下类型:
ArrayList<Object> name = new ArrayList<Object>();
同样,对于数组,我们有:
Object[] name = new Object[size];
现在,我们当然不能声明以下类型:
ArrayList<Object> name = new ArrayList<AnotherObject>();
两次指定同一对象的类型和名称对我来说似乎总是多余的。上述声明中的冗余可以通过以下方式轻松完成:
ArrayList<Object> name = new();
我是否有任何具体原因错过了为什么按照这样做完成的原因?
答案 0 :(得分:5)
不是。至少,不再是。现在你可以做到:
ArrayList<Object> name = new ArrayList<>();
你不能放弃第二个ArrayList
,因为它不一定要与第一个匹配。例如,您可以这样做:
List<Object> name = new ArrayList<>();
,您将获得ArrayList
,但会将其视为List
。
答案 1 :(得分:3)
从JDK7开始,存在类型推断。您无需在右侧指定类型。在这里查看示例:http://www.javacodegeeks.com/2012/05/type-inference-from-java-7.html
您可以这样写:
List<Object> values = new ArrayList<>();
答案 2 :(得分:2)
那里有一本尘土飞扬的书,讲的是为什么它按原样完成,但让我们特别看一下ArrayList
的声明。
要在其上添加一个引脚:在Java 6发布时,在新增泛型时减少详细程度的能力不在语言中。
This is the grammar for declaring a new
instance of a reference, back in Java 6.
ClassInstanceCreationExpression:
new TypeArguments (opt) ClassOrInterfaceType ( ArgumentList (opt) )
ClassBody (opt)
Primary. new TypeArguments (opt) Identifier TypeArguments (opt) (
ArgumentList (opt) ) ClassBody (opt)
ArgumentList:
Expression
ArgumentList , Expression
第二个产品,或者更具体地说, TypeArguments 令牌正在管理我们可以放在那里的东西。
That changes in Java 7,引入钻石操作员。
ClassInstanceCreationExpression:
new TypeArguments (opt) TypeDeclSpecifier TypeArgumentsOrDiamond (opt)
( ArgumentList (opt) ) ClassBody (opt)
Primary . new TypeArguments (opt) Identifier TypeArgumentsOrDiamond (opt)
( ArgumentList (opt) ) ClassBody (opt)
TypeArgumentsOrDiamond:
TypeArguments
<>
ArgumentList:
Expression
ArgumentList , Expression
由于 TypeArgumentsOrDiamond 令牌,所以详细程度不再需要,但无论如何,它仍然受到较新版本Java的支持。
以你的例子为例,我们为什么不能这样做:
ArrayList<Object> name = new();
要想到的主要事情是,如果要创建List
的实例,这是一个接口,因此无法实例化,new()
方法将如何知道拉回来的种类?它总是会退回ArrayList
吗?一个LinkedList
?或者您自己的一种列表?如果没有你告诉它,Java将如何知道哪一个是正确的?
更直接地说,这个会产生什么......
List<Object> name = new();
...如果我们可以选择延伸ArrayList
的{{1}},LinkedList
或SpecialUtilityList
?
答案 3 :(得分:1)
也许您熟悉其他语言,例如C#或C ++,它们能够推断出变量的类型; e.g。
var x = new MyObjectType(); // C#
或
auto x = someMethodThatReturnsSomething(); // C++
如果习惯上述任何一种语言,Java会以“错误的方式”进行类型推理:您可以在右侧省略泛型类型的类型参数:
List<MyObjectType> = new ArrayList<>();
然而,尽管起初看起来似乎不直观,但这就是类型推断的工作方式,它是一致的,并且在其他情况下具有优势;例如,您可以将Collections.emptyMap()
传递给采用Map<Integer, MyObjectType>
的方法,编译器可以将其解析出来,而无需指定您希望emptyMap
返回的地图类型。
至于为什么你仍然需要在LHS上指定类型,那就是Java哲学 - 你在LHS上指定了你想要的接口和你想要的具体类型 RHS。
答案 4 :(得分:0)
从Java 10开始,可以省略这些冗余信息,我们可以选择让编译器使用var
来推断类型,例如
var objArray = new Object[10]; // (objArray instanceof Object[]) == true
var stringList = new ArrayList<String>(); // (stringList intanceof ArrayList) == true
要处理var
,编译器会查看所谓的initializer
(声明的右侧),并将其类型用于变量。详细信息可以参考JEP 286。