我今天看到了这段代码:
ImmutableMap<Class<? extends ClientCommand>, CommandProcessorInterface> immutableMap =
ImmutableMap.<Class<? extends ClientCommand>, CommandProcessorInterface>of(...
这种语法是什么意思?
ImmutableMap.<Class ..
我知道仿制品就在课程名称之后。否?
有什么区别:
ImmutableMap<Class..
和ImmutableMap.<Class..
答案 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()...
如果你真的想省略 builder
和 build
的类型参数,它们都必须有用于推断的目标类型:
ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
ImmutableMap<String, Integer> immutableMap = builder.build();