点运算符`.`(在通用参数之前)是什么意思?

时间:2014-11-27 08:59:36

标签: java generics syntax guava

我今天看到了这段代码:

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

这种语法是什么意思?

ImmutableMap.<Class ..

我知道仿制品就在课程名称之后。否?

有什么区别:

ImmutableMap<Class..ImmutableMap.<Class..

4 个答案:

答案 0 :(得分:20)

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

它与您调用static方法几乎相同,嵌套在某个类中:

SomeClass.staticMethod();

对于您的方法定义了类型参数的情况,您可以显式提供泛型类型,如下所示:

SomeClass.<Type>genericStaticMethod();

并回答你的最后一个问题:

  

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

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

答案 1 :(得分:4)

通用方法是使用任何泛型类型参数声明的方法。 请参阅文档here。该方法的泛型类型不必与声明类的任何泛型类型参数相关。该课程可能是也可能不是通用的。

当调用泛型方法(静态或非静态)时,您可以指定泛型类型,但通常不会看到它,因为它通常是自动检测的。您找到的语法是指定它的语法。

如果有一个声明如下的方法:

<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);

答案 2 :(得分:3)

它涉及静态方法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中的泛型类型推断变得更强一些。

答案 3 :(得分:0)

泛型方法的完整调用类型是(如Generic Methods所说):

// 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);

这称为Type Inference

查看 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();

有两个连续的泛型方法:builder & build。对于后一种方法,由于目标类型推断,可以省略类型参数。对于前一种方法,情况并非如此。没有它可以推断的目标类型,所以类型参数必须写在这里:

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

如果你真的想省略 builderbuild 的类型参数,它们都必须有用于推断的目标类型:

ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
ImmutableMap<String, Integer> immutableMap = builder.build();