
例子如下:
public class Test04{
public <T> ArrayList<T> f(T t ) {
return null;
}
public void m(ArrayList<String> list) {
//System.out.println(list.getClass().getName());
}
public <K> void get() {
// f() 通过句柄中的<String>,得知返回的ArrayList<T>中的T代表什么类型
ArrayList<String> list = f(null);// 通过泛型方法及类型推断得到了list
m(list);// m方法可以使用该list
}
}
对ArrayList<String> list = f(null);这条语句进行重点的分析,首先从Attr.attrVarDef()方法看起,记录两个状态,如下:

在代码要执行这个语句中的init部分时,这个树的状态如下:
再进入visitApply()方法后,如下:

进入visitIdentifier()方法后,如下:

在visitIdentifier()方法中要对f这个唯一标识填充sym与type属性,通过如下调用链查找sym符号:
(1)Resolve.resolveMethod() 开始走三步进行方法选定
(2)Resolve.findFun() 通过变换outer环境来调用下面的方法查找方法,查找namedImportScope与starImportScope来找方法
(3)Resolve.findMethod() 循环查找所有接口类及其父类
(4)Resolve.selectBest() 在调用rawInstantiate()方法之后会对方法调用权限进行检查,然后可能会调用mostSpecific()方法
(5)Resolve.rawInstantiate() 如果方法需要实例化,则调用下面的方法。如果不需要实例化,则调用checkRawArgumentsAcceptable()方法进行参数验证。
(6)infer.instantiateMethod() 对方法上声明的形式参数中含有新类型变量的全部再次封装为undetvar变量,
目的是在调用types.isConvertible()或者types.isSubtypeUnchecked()时,可能为了使两个方法调用返回true,往undetvar的lobounds中追加具体的实际参数类型。
不过这里的实际参数传递的是null,所以什么也没有追加。这样调用minimizeInst()方法后就inst属性只能是bottom类型了。
在这个方法中,如果最终不能将类型变量全部实例化,那么就会封装为一个UninferredMethodTypeImpl对象返回,后续继续进行类型推断实例化。
通过第一步方法就能找到要调用的f方法,最终得到sym后,
(1)调用checkIdentifier()来得到theComputedType
checkIdentifier()方法中最后一步调用如下方法
check(tree, ownTypeTagsType,protoTypesTagType,sym.kind, protoKindsSymbol);
然后为tree.type赋了值。传递check()方法的4个值如下:
sym.kind=16,而protoKindsSymbol=12
其中的值如下:


(2)调用checkMethod()来得到ownTypeTagsType
(3)resolve.instantiate()来得到owntype,方法中对异常进行了简单的捕获
(4)rawInstantiate()
(5)infer.instantiateMethod() 调用这个方法得到一个UninferredMethodTypeImpl对象返回,而上次调用时直接弃掉了结果。
593

被折叠的 条评论
为什么被折叠?



