如果我们有通用方法
class SClass{
public static <T> ArrayList<T> listFactory(){ return new ArrayList<T>(); }
}
我们可以在调用此方法时显式定义type-parameter T
。
SClass.<?>listFactory();//compile error
SClass.<List<?>>listFactory();//ok
为什么我们无法使用类型参数listFactory
调用?
,但可以使用List<?>
?
答案 0 :(得分:5)
rules of method invocation are described in the Java Language Specification。在这种情况下,我们感兴趣
方法调用表达式用于调用类或实例 方法
[...] TypeName . NonWildTypeArguments Identifier ( ArgumentListopt )
<?>
是狂野类型,<List<?>>
不是。
至于原因,请考虑
SClass.<?>listFactory();//compile error
你甚至可以在<?>
中使用listFactory()
做什么? ?
未知。你将无法做到
new ArrayList<?>();
如果a中使用的任何类型参数,则是编译时错误 类实例创建表达式是通配符类型参数 (§4.5.1)。
但是你也不能把它用在其他任何东西上。
答案 1 :(得分:1)
为什么我们不能使用类型参数?调用listFactory,但可以使用List?
实例创建在类实例创建表达式中,如果类型是参数化的 类型,那么所有类型参数都不是通配符。我认为它是一样的:
List<?> list = new ArrayList<?>(); // compile-time error
只允许实例创建中的顶级参数包含通配符。 允许使用嵌套通配符。因此,以下是合法的:
List<List<?>> lists = new ArrayList<List<?>>(); // ok
这就是为什么:
SClass.<List<?>>listFactory();//ok
通用方法调用如果泛型方法调用包含显式类型参数,则为那些类型 参数不能是通配符。
class SClass{
public static <T> ArrayList<T> listFactory(){ return new ArrayList<T>(); }
}
您可以选择推断类型参数,也可以传递显式类型 参数。以下两种都是合法的:
List<?> list = Lists.factory();
List<?> list = Lists.<Object>factory();
如果传递了显式类型参数,则它不能是通配符:
List<?> list = Lists.<?>factory(); // compile-time error
允许使用嵌套通配符:
List<List<?>> = Lists.<List<?>>factory(); // ok
Java设计师每个人都记得 通配符类型是一些普通类型的简写,所以他们认为最终每一个 对象应该使用普通类型创建。目前尚不清楚这种限制是否存在 必要的,但不太可能是一个问题。
答案 2 :(得分:0)
而不是SClass.<?>listFactory()
,您可以使用:
class CompletelyUnrelatedBogusClass { }
SClass.< CompletelyUnrelatedBogusClass >listFactory();
由于?
未知,这意味着它不会假设它是什么。这意味着您可以将任何引用类型放在那里,这是正确的。