编译器在以下代码中如何处理对 << T >> 的引用,因为该方法不采用允许推断 T 的参数?是否对可以放入列表的对象类型设置了任何限制?是否甚至在我将字符串添加到列表的那一行发生了转换?我的第一个想法是,如果没有任何东西可以从中推断出 T,T 就变成了一个 Object 类型。提前致谢。
public class App {
private <T> void parameterizedMethod()
{
List<T> list = new ArrayList<>();
for(int i = 0; i < 10; i++)
{
list.add((T)new String()); //is a cast actually occurring here?
}
}
public App()
{
parameterizedMethod();
}
public static void main(String[] args) {
new App();
}
}
最佳答案
这最初是由 18.1.3 决定的:
When inference begins, a bound set is typically generated from a list of type parameter declarations
P<sub>1</sub>, ..., P<sub>p</sub>
and associated inference variablesα<sub>1</sub>, ..., α<sub>p</sub>
. Such a bound set is constructed as follows. For each l (1 ≤ l ≤ p):
If
P<sub>l</sub>
has noTypeBound
, the boundα<sub>l</sub> <: Object
appears in the set.Otherwise, for each type
T
delimited by&
in theTypeBound
, the boundα<sub>l</sub> <: T[P<sub>1</sub>:=α<sub>1</sub>, ..., P<sub>p</sub>:=α<sub>p</sub>]
appears in the set; [...].
在推断结束时,绑定(bind)集“解析”为推断类型。在没有任何附加上下文的情况下,绑定(bind)集将仅包含基于类型参数声明的初始边界。
与 α<sub>l</sub> <: Object
形式的绑定(bind)表示 α<sub>l</sub>
(推理变量)是 Object
或 Object
的子类型.此绑定(bind)解析为 Object
.
所以在你的情况下,是的,Object
推断。
如果我们声明一个类型绑定(bind):
private <T extends SomeType> void parameterizedMethod()
然后 SomeType
将被推断。
在这种情况下实际上没有转换(删除)。这就是为什么它是“未检查的”。仅当对象因以下原因而暴露时才会发生转换:
<T> T parameterizedMethodWithAResult()
{
return (T) new String();
}
// the cast happens out here
Integer i = parameterizedMethodWithAResult();
// parameterizedMethodWithAResult returns Object actually,
// and we are implicitly doing this:
Integer i = (Integer) parameterizedMethodWithAResult();
Are any restrictions being placed on what type of object can be placed into the list?
语义上(编译时),是的。请注意,限制是在方法之外确定的。 在 方法内部,我们不知道该限制实际上是什么。所以我们不应该把 String
在List<T>
.我们不知道什么T
是。
实际上(运行时),没有。这只是一个 List
并且没有经过检查的类型转换。 parameterizedMethod
不会导致异常...但这只适用于这种孤立的例子。这种代码很可能会导致问题。
关于java - 如果 <T> 不是输入参数,参数化方法如何解析?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30516460/