我找到了一个'不寻常'的通用语法,例如:
Arrays.<String>asList(...);
Collections.<String>emptyList();
显然,这些方法的结果是通用的。这种语法是否用于类型检查? Object
数组不能是Arrays.<String>asList(...)
的参数。
答案 0 :(得分:21)
<typearg>methodname
是显式指定通用方法的类型参数的语法
使用泛型类时,通常必须指定类型参数(例如String
):
ArrayList<String> list = new ArrayList<String>();
使用泛型方法,通常不会传递类型参数:
public static <T> void foo(T param) { }
...
String s = ...;
MyClass.foo(s);
您会注意到我们没有在哪里明确指定代码我们想要String
版foo
,即没有明确的类型参数<String>
,就像我们在使用时看到的那样通用类(List<String>
)。
编译器正在做一些编译魔术来根据上下文推断泛型类型参数。这是一件好事而且非常强大。
但是,有时编译器无法自动推断类型参数:
public static <T> void bar() { T myLocalVar = ...; ... }
MyClass.bar();
我们试图调用bar
的具体版本,即此调用的类型参数是什么?不知道?好吧,编译器也没有。我们必须显式地声明类型参数,就像我们在使用泛型类时通常所做的那样:
MyClass.<String>bar();
另见:
除了:值得一提的是,Java 7将添加所谓的菱形运算符,以允许我们让编译器在使用泛型类时推断类型参数:< / p>
ArrayList<String> list = new ArrayList<String>();
变为
ArrayList<String> list = new ArrayList<>();
答案 1 :(得分:8)
这是显式指定泛型方法的类型参数的方法。在大多数情况下,编译器可以推断它,但有时需要明确说明。
答案 2 :(得分:1)
上面的答案几乎解决了你的问题,但是如果你想要一个特定的例子来说明Java的泛型类型推断失败并以这种方式明确地说明它节省了一天,请考虑以下类定义:
public class A { }
public class B extends A { }
public class C extends A { }
然后下面的代码工作正常(即Java的类型推断成功):
List<Class<? extends A>> list = ImmutableList.of(B.class, C.class);
但是对于以下内容,它无法编译:
List<Class<? extends A>> list = ImmutableList.of(B.class);
这是对的;奇怪的是,通过删除参数,我们混淆了类型推理系统,因为B.class
和C.class
的“最近的共同后代”是A.class
,但是B.class
本身就是B.class
,它(由于Java的泛型中缺乏协方差)与List<Class<? extends A>>
不匹配。在这种情况下,您别无选择,只能使用:
List<Class<? extends A>> list = ImmutableList.<Class<? extends A>>of(B.class);
由于B
确实扩展了A
,因此编译(并运行)就好了。
我希望这个演示强调操作员的用处。
答案 3 :(得分:0)
另外,Java 7编译器支持类型推断之后。请考虑以下类定义:
public class A { }
public class B extends A { }
public class C extends A { }
以下所有案例都有效:
List<Class<? extends A>> list0 = Arrays.asList(B.class, C.class);
List<Class<? extends A>> list1 = Arrays.asList(B.class);
List<A> list2 = Arrays.asList(new B());
List<A> list3 = Arrays.asList(new B(), new C());
List<? extends A> list4 = Arrays.asList(new B(), new C());
List<? extends A> list5 = Arrays.asList(new B());