Java数组和ArrayList声明中的冗余措辞

时间:2015-12-19 22:43:43

标签: java arrays arraylist

Java中典型的ArrayList声明属于以下类型:

ArrayList<Object> name = new ArrayList<Object>();

同样,对于数组,我们有:

Object[] name = new Object[size];

现在,我们当然不能声明以下类型:

ArrayList<Object> name = new ArrayList<AnotherObject>();

两次指定同一对象的类型和名称对我来说似乎总是多余的。上述声明中的冗余可以通过以下方式轻松完成:

ArrayList<Object> name = new();

我是否有任何具体原因错过了为什么按照这样做完成的原因?

5 个答案:

答案 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}},LinkedListSpecialUtilityList

答案 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