点运算符 `.`(在泛型参数前面)是什么意思?

24

我今天看到了这段代码:

    ImmutableMap<Class<? extends ClientCommand>, CommandProcessorInterface> immutableMap =
            ImmutableMap.<Class<? extends  ClientCommand>, CommandProcessorInterface>of(...

这个语法是什么意思?

ImmutableMap.<Class ..

我知道泛型是写在类名后面的。对吗?

ImmutableMap<Class..ImmutableMap.<Class.. 有什么区别?


2
这是静态方法 of 的通用参数,而不是类本身的参数。 - Dmitry Ginzburg
4个回答

32

这意味着您正在调用 ImmutableMap 类中的一个通用静态方法,名为 of

这与调用某个类中嵌套的 static 方法基本相同:

SomeClass.staticMethod();

如果您的方法定义了类型参数,您可以明确提供泛型类型,具体操作如下:

SomeClass.<Type>genericStaticMethod();

针对你的最后一个问题作出回答:

ImmutableMap<Class...>ImmutableMap.<Class... 的区别是什么?

第一种通常用于创建泛型类的实例。它用于在类级别上定义泛型类型,而第二种则用于调用嵌套在某个类中的泛型静态方法。


4
通常情况下不需要提供它。请查看文档fromArrayToCollection(sa, cs); // 推断 T 为 String - aalku
2
可能可以从返回类型转换(或赋值)中推断出来,但并非总是如此。我只是说“你需要提供通用类型”,这并不总是正确的。 - aalku
3
我认为说“你需要”这种表述是错误的,甚至可以说是彻底错误的。 - xehpuk

12

这涉及到一个静态方法ImmutableMap.of。它有自己的泛型参数。

class Test {

static <T> T f() { return null; }

void t() {
    String s = Test.f();                 // Inferred from LHS.
    String t = Test.<String>f();         // Not needed.
    int n = Test.<String>f().length();   // Needed.
}

在你的情况下似乎并不需要,但我说话有点冒险,因为Java 8中的通用类型推断变得更强了一些。


7
通用方法是指声明了任何通用类型参数的方法。 可在此处查看文档(链接)。该方法的通用类型不必与声明类的任何通用类型参数相关联。该类可以是通用的,也可以不是通用的。
当调用通用方法(静态或非静态)时,您可以指定通用类型,但通常不会看到它,因为它通常是自动检测到的。你找到的语法就是指定它的语法。
如果有这样的方法声明:
<T> void fromArrayToCollection(T[] a, Collection<T> c) { ...

你可以这样调用:

Integer[] a = ...
ArrayList<Integer> l = ...
x.fromArrayToCollection(a, l);

但是如果你有像这样的一个:
<T> Collection<T> myMethod(int c) {
  return new ArrayList<T>(c);
}

那么你有两种方法可以向编译器澄清类型。你可以用两种方式之一在调用中提供足够的信息。

第一种是在调用时指定类型:

Object c = x.<Integer>myMethod(5);

另一种方法是使用类型转换(通过将值分配给变量来明确或隐式地进行)。
Collection<Integer> c = x.myMethod(5);

Object c = & 显式/隐式是我回答中缺失的部分。点赞! - Joop Eggen

2
通用方法的完整调用类型是(如通用方法所述):
// use Collections#emptyList as an example
List<String> a = Collections.<String>emptyList();

可以简化为:
// use Collections#emptyList as an example
List<String> a = Collections.emptyList();

另一个例子:
List<String> a = ...;
String s = a.<String>get(0);

信件类型参数也可以简化为:
String s = a.get(0);

This is called 类型推断
请查看Guava的几个ImmutableMap示例:
// type parameter can be omitted
ImmutableMap<String, Integer> map = ImmutableMap.<String, Integer>of("a", 1);

可以简化为:

可以简化为:

ImmutableMap<String, Integer> map = ImmutableMap.of("a", 1);

这是由目标类型推断出来的。
但对于这个:
// type parameter can not be omitted
ImmutableMap<String, Integer> map = ImmutableMap.<String, Integer>builder().build();

这很令人困惑。实际上,完整的格式是:
// the latter type parameter can be omitted
ImmutableMap<String, Integer> map = ImmutableMap.<String, Integer>builder().<String, Integer>build();

有两个连续的通用方法:builderbuild。对于后者的方法,由于目标类型推断,类型参数可以省略。对于前者的方法,则不是这种情况。它没有目标类型进行推断,因此必须在此处编写类型参数:

ImmutableMap<String, Integer> map = ImmutableMap.<String, Integer>builder()...

如果您真的想要省略构建器和构建函数的类型参数,它们都必须具有用于推断的目标类型:
ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
ImmutableMap<String, Integer> immutableMap = builder.build();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接