不寻常的通用语法:Arrays。<string> asList(...)</string>

时间:2011-01-28 15:00:29

标签: java generics

我找到了一个'不寻常'的通用语法,例如:

Arrays.<String>asList(...);
Collections.<String>emptyList();

显然,这些方法的结果是通用的。这种语法是否用于类型检查? Object数组不能是Arrays.<String>asList(...)的参数。

4 个答案:

答案 0 :(得分:21)

<typearg>methodname是显式指定通用方法的类型参数的语法

使用泛型类时,通常必须指定类型参数(例如String):

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

使用泛型方法,通常不会传递类型参数:

public static <T> void foo(T param) {   }
...
String s = ...;
MyClass.foo(s);

您会注意到我们没有在哪里明确指定代码我们想要Stringfoo,即没有明确的类型参数<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<>();

What is the point of the diamond operator in Java 7?

答案 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.classC.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());