解释Collections。<String> emptyList()的语法


70

我只是研究了通用编程,List<E>接口和ArrayList,所以我可以理解下面的语句。

ArrayList<String> list = new ArrayList<String>();

但是我不理解在浏览网络时看到的下一条语句。

List<String> list2 = Collections.<String>emptyList();
  1. 什么Collections啊 为什么不是Collections<E>还是Collections<String>
  2. 为什么<String>将方法名称放在前面emptyList

emptyList<String>()对于Generic是否正确?)

  1. 该声明是什么意思?

Collections是一个Java类。
2014年

39
这是一个完全正确的问题。不知道它是否被如此严厉地对待。对于不了解静态方法泛型的人来说,这可能是一个令人困惑的声明。投票重新开放。
Qix-蒙尼卡(Monica)2014年

3
还投票重新开放。该问题的标题可能太宽泛,但是正文中的实际问题却非常具体。也许编辑标题总比结束好。
TM。

3
在我看来,回答这个问题需要解释的概念数量如此之多,以至于答案几乎构成了Java入门教程。但是,这是我对通用方法的解释。至于问题2,请阅读有关静态导入的信息。
克里斯·马丁

2
@ChrisMartin参见给出的答案。他们似乎做得很好。OP理解泛型,但是方法泛型是一个(可以理解的)新概念,在野外并不常见。
Qix-蒙尼卡(Monica)2014年

Answers:


58

该行通过使用泛型类型参数调用静态方法来创建一个空字符串列表。

Collections类内部,有一个静态方法emptyList声明为:

public static final <T> List<T> emptyList() {
    return (List<T>) EMPTY_LIST;
}

这具有通用类型参数T。我们使用以下方法调用此方法:

List<String> list = Collections.emptyList();

并被T推断为是String由于list

我们还可以T通过在调用时将其放在尖括号中来指定其类型emptyList。如果我们想要比推断的类型更具体的类型,则可能需要这样做:

List<? extends Object> list = Collections.<String>emptyList();

emptyList<String>()是不正确的,因为该放置仅在创建泛型类的实例而不是调用方法时有效。当使用new两个可能的类型参数时,类名之前的仅用于构造函数,类名之后的用于整个实例,因此对于类:

class MyClass<A> {
    public <B> MyClass(A a, B b) {
        System.out.println(a + ", " + b);
    }
}

我们可以调用它的构造,其中AStringBInteger这样的:

MyClass<String> a = new <Integer>MyClass<String>("a", 3);

或使用类型推断:

MyClass<String> a = new MyClass<>("a", 3);

也可以看看:


4
可能要提到的Collections是那些提供静态方法的类之一。它本身不打算实例化(并且不能依次实例化)。
Qix-蒙尼卡(Monica)2014年

我不是Java专家,但是在我看来,这foo<T>()根本就不是“调用构造函数”,即使最终的对象构造导致调用foo构造函数(在实例化a的所有其他步骤中foo) 。这样,与通用方法调用语法就没有实际的不一致或差异<T>bar()(这来自C ++背景,让我只想说这是很奇怪的!)。
Lightness Races in Orbit

9
我检查了构造函数的语法,结果发现构造函数也可以具有自己的类型参数,因此我们可以使用包含两个类型参数表达式的语法,例如new <String>MyClass<Integer>(2)
fgb

@fgb呵呵...这是新的。我想我从未在野外见过这样的东西。有趣!
Qix-蒙尼卡(Monica)

“ emptyList <String>()不正确,因为该位置仅在调用构造函数而不是静态方法时才有效”。由于这个问题是关于泛型方法的,所以听起来您正在谈论泛型构造函数。但是你不是。SomeClass<String>()用于使用非泛型构造函数创建泛型类的实例。要使用泛型构造函数创建类的实例,您可以执行new <String> SomeClass()
newacct 2014年

11

什么Collections啊 为什么不是Collections<E>还是Collections<String>

Collections 是一个JDK类。

此类仅包含对集合进行操作或返回集合的静态方法。它包含对集合进行操作的多态算法,“包装器”(包装器),该包装器返回由指定集合支持的新集合,以及其他一些零碎的结局。

它不是通用的,无法实例化。

为什么<String>将方法名称放在前面emptyList

Collections#emptyList是一种通用方法。在这里,我们明确指定类型参数String

emptyList<String>()对于Generic是否正确?)

不,在Java中,方法的通用类型参数位于方法名称之前。

该声明是什么意思?

我们正在调用静态emptyList方法,并将其返回值分配给type变量List<String>


9

简而言之,这将创建一个空的,不变的字符串列表。

让我们一点一点地看一下表达式。

Collections是类的名称。从Javadoc

此类仅包含对集合进行操作或返回集合的静态方法。它包含对集合进行操作的多态算法,“包装器”(包装器),该包装器返回由指定集合支持的新集合,以及其他一些零碎的结局。

emptyList()是在Collections类(Javadoc)中定义的静态方法的名称。这是一个通用方法,<String>inCollections.<String>emptyList()指定通用类型参数。

该方法返回一个List<T>,在这种情况下为List<String>:字符串列表。更具体地说,它返回一个空的不可变的字符串列表。


+1突出显示(尽管存在于文档中)返回集合的不变性

6

1.Collection是一个接口,collections是一个静态类,仅包含对集合进行操作或返回collection的静态方法。因此,我们不能使用Collections<E>Collections<String>

2. <String>before emptyList(用于获取不可变的空列表)表示只能将String值添加到其中。喜欢:

list2.add("A");
list2.add("B");

3.该语句意味着它将创建一个类型为List的不可变的空列表。

您可以查看以下链接:Java Collection和Collections之间的区别


2
denotes that only String values can be added to it.更精确的描述是:将方法的参数类型声明为String,以便返回值是String的同类List。
nhahtdh 2014年

6

首先,Collections是静态方法的帮助程序库,可对各种类型的集合进行操作。如果您已完成任何C ++编程,则它<algorithm>与函数库非常相似。

在这种情况下,您要调用static方法emptyList(),该方法返回特定类型的空列表。由于这些方法仍然需要一个类型,但是Collections方法可以引用许多类型,因此您必须在调用时指定类型。

为了调用通用方法,您必须在方法名称之前使用参数列表(即<String>)来调用它。

List<String> someList = Collections.<String>emptyList();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.