【发布时间】:2011-06-17 07:25:26
【问题描述】:
我发现了一个“不寻常”的通用语法,例如:
Arrays.<String>asList(...);
Collections.<String>emptyList();
显然,方法的结果是通用的。这种语法是用于类型检查的吗? Object 数组不能作为 Arrays.<String>asList(...) 的参数。
【问题讨论】:
我发现了一个“不寻常”的通用语法,例如:
Arrays.<String>asList(...);
Collections.<String>emptyList();
显然,方法的结果是通用的。这种语法是用于类型检查的吗? Object 数组不能作为 Arrays.<String>asList(...) 的参数。
【问题讨论】:
<typearg>methodname 是显式指定泛型方法的类型参数的语法
当您使用泛型类时,通常必须指定类型参数(例如String):
ArrayList<String> list = new ArrayList<String>();
使用泛型方法,您通常不会传递类型参数:
public static <T> void foo(T param) { }
...
String s = ...;
MyClass.foo(s);
您会注意到我们没有在代码中明确指定我们想要foo 的String 版本,即没有像我们在使用泛型类时看到的那样指定明确的类型参数<String> (@987654331 @)。
编译器正在使用一些编译器魔法来根据上下文推断泛型类型参数。这是一件很棒的事情,而且非常强大。
但是,有时编译器无法自动推断类型参数:
public static <T> void bar() { T myLocalVar = ...; ... }
MyClass.bar();
我们试图调用bar 的具体版本,即这个调用的类型参数是什么?好吧,编译器也没有。我们必须显式声明类型参数,就像我们通常在使用泛型类时所做的那样:
MyClass.<String>bar();
另见:
除此之外: 值得一提的是,Java 7 将添加所谓的菱形运算符,以便我们现在也可以让编译器在使用泛型类时推断类型参数:
ArrayList<String> list = new ArrayList<String>();
变成
ArrayList<String> list = new ArrayList<>();
【讨论】:
这是您显式指定泛型方法的类型参数的方式。在大多数情况下,编译器可以推断出来,但有时需要明确说明。
【讨论】:
<>)编写new ArrayList<>(),然后推理将魔法发生。
上面的答案几乎可以解决您的问题,但是如果您想要一个 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,所以编译(和运行)就好了。
我希望这个演示能够强调操作符的实用性。
【讨论】:
另外,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());
【讨论】: