如果在Java中创建泛型类(该类具有泛型类型参数),您可以使用泛型方法(该方法采用泛型类型参数)吗?
请考虑以下示例:
public class MyClass {
public <K> K doSomething(K k){
return k;
}
}
public class MyGenericClass<T> {
public <K> K doSomething(K k){
return k;
}
public <K> List<K> makeSingletonList(K k){
return Collections.singletonList(k);
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所期望的泛型方法,我可以调用任何对象的doSomething(K)实例MyClass:
MyClass clazz = new MyClass();
String string = clazz.doSomething("String");
Integer integer = clazz.doSomething(1);
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试使用MyGenericClass 没有指定泛型类型的实例,我调用doSomething(K)返回一个Object,无论K传入什么:
MyGenericClass untyped = new MyGenericClass();
// this doesn't compile - "Incompatible types. Required: String, Found: Object" …Run Code Online (Sandbox Code Playgroud) List<String> list = new ArrayList(); 将导致编译器警告.
但是,以下示例编译时没有任何警告: List<String> list = new ArrayList<>();
我很好奇为什么需要引入钻石操作员.为什么不只是对构造类型推断,如果类型参数是不存在(因为它已经在Java静态方法做,像谷歌番石榴集合库开发)
编辑:使用millimoose答案作为起点我查看了实际上是什么类型的擦除,它不只是删除所有类型信息.编译器实际上做了一些(从官方文档复制):
public abstract class A<T> {
public static void test(A i) { for (String s : i.get()) {} }
public abstract Iterable<String> get();
}
Run Code Online (Sandbox Code Playgroud)
为什么上面的代码我得到:
incompatible types
required: String
found: Object
Run Code Online (Sandbox Code Playgroud)
但是如果我将test方法的参数改为A<Object>,它会编译好吗?为什么未定义的变量泛型参数会丢弃它的方法返回类型的显式泛型参数?