javac之Inferring Type Arguments Based on Actual Arguments
We use the following notational conventions in this section:
Type expressions are represented using the letters A, F, U, V, and W. The letter A is only used to denote the type of an actual argument, and F is only used to denote the type of a formal parameter.
Type parameters are represented using the letters S and T
Arguments to parameterized types are represented using the letters X and Y.
Generic type declarations are represented using the letters G and H.
Inference begins with a set of initial constraints of the form A << F, A = F, or A >> F, where U << V indicates that type U is convertible to type V by method invocation conversion (§5.3), and U >> V indicates that type V is convertible to type U by method invocation conversion.

These constraints are then reduced to a set of simpler constraints of the forms T :> X, T = X, or T <: X, where T is a type parameter of the method. This reduction is achieved by the procedure given below.
Given a constraint of the form A << F, A = F, or A >> F:
If F does not involve a type parameter Tj then no constraint is implied on Tj.
e.g
public <T extends InputStream> void test1(String a) { ... }
Otherwise, F involves a type parameter Tj, and there are four cases to consider.
1. If A is the type of null, no constraint is implied on Tj.
2. Otherwise, if the constraint has the form A << F:
3. Otherwise, if the constraint has the form A = F:
4. Otherwise, if the constraint has the form A >> F:
1、the constraint has the form A << F
If A is a primitive type, then A is converted to a reference type U via boxing conversion and this algorithm is applied recursively to the constraint U << F.
If A is Reference type ,than:
if F = Tj, then the constraint Tj
:>A is implied.If F = U
[], where the type U involves Tj, then if A is an array type V[], or a type variable with an upper bound that is an array type V[], where V is a reference type, this algorithm is applied recursively to the constraint V << U.This follows from the covariant subtype relation among array types. The constraint A << F in this case means that A << U
[]. A is therefore necessarily an array type V[], or a type variable whose upper bound is an array type V[]- otherwise the relation A << U[]could never hold true. It follows that V[]<< U[]. Since array subtyping is covariant, it must be the case that V << U.If F has the form G
<..., Yk-1, U, Yk+1, ...>, where U is a type expression that involves Tj, then if A has a supertype of the form G<..., Xk-1, V, Xk+1, ...>where V is a type expression, this algorithm is applied recursively to the constraint V = U.For simplicity, assume that G takes a single type argument. If the method invocation being examined is to be applicable, it must be the case that A is a subtype of some invocation of G. Otherwise, A << F would never be true.
In other words, A << F, where F = G
<U>, implies that A << G<V>for some V. Now, since U is a type expression (and therefore[因此,所以], U is not a wildcard type argument), it must be the case that U = V, by the non-variance of ordinary parameterized type invocations.The formulation above merely generalizes this reasoning to generics with an arbitrary number of type arguments.
If F has the form G
<..., Yk-1,?extendsU, Yk+1, ...>, where U involves Tj, then if A has a supertype that is one of:G
<..., Xk-1, V, Xk+1, ...>, where V is a type expression. Then this algorithm is applied recursively to the constraint V << U.Again, let's keep things as simple as possible, and consider only the case where G has a single type argument.
A << F in this case means A << G
<?extendsU>. As above, it must be the case that A is a subtype of some invocation of G. However, A may now be a subtype of either G<V>, or G<?extendsV>, or G<?superV>. We examine these cases in turn. The first variation is described (generalized to multiple arguments) by the sub-bullet directly above. We therefore have A = G<V><< G<?extendsU>. The rules of subtyping for wildcards imply that V << U.G
<..., Xk-1,?extendsV, Xk+1, ...>. Then this algorithm is applied recursively to the constraint V << U.Extending the analysis above, we have A = G
<?extendsV><< G<?extendsU>. The rules of subtyping for wildcards again imply that V << U.Otherwise, no constraint is implied on Tj.
Here, we have A = G
<?superV><< G<?extendsU>. In general, we cannot conclude anything in this case. However, it is not necessarily an error. It may be that U will eventually be inferred to beObject, in which case the call may indeed be valid. Therefore, we simply refrain[避免,节制] from placing any constraint on U.
If F has the form G
<..., Yk-1,?superU, Yk+1, ...>, where U involves Tj, then if A has a supertype that is one of:G
<..., Xk-1, V, Xk+1, ...>. Then this algorithm is applied recursively to the constraint V >> U.As usual, we consider only the case where G has a single type argument.
A << F in this case means A << G
<?superU>. As above, it must be the case that A is a subtype of some invocation of G. A may now be a subtype of either G<V>, or G<?extendsV>, or G<?superV>. We examine these cases in turn. The first variation is described (generalized to multiple arguments) by the sub-bullet directly above. We therefore have A = G<V><< G<?superU>. The rules of subtyping for wildcards imply that V >> U.G
<..., Xk-1,?superV, Xk+1, ...>. Then this algorithm is applied recursively to the constraint V >> U.We have A = G
<?superV><< G<?superU>. The rules of subtyping for lower-bounded wildcards again imply that V >> U.Otherwise, no constraint is implied on Tj.
Here, we have A = G
<?extendsV><< G<?superU>. In general, we cannot conclude anything in this case. However, it is not necessarily an error. It may be that U will eventually be inferred to the null type, in which case the call may indeed be valid. Therefore, we simply refrain from placing any constraint on U.
Otherwise, no constraint is implied on Tj.
e.g
class A<U> { }
public class Test {
public <T extends Number> void test(
T a,
T[] b,
A<T> c,
A<? extends T> d,
A<? super T> e) {
}
public void tt(){
int a = 2;
// int[] b = new int[]{2,4};
Integer[] b = new Integer[]{1,2,3};
A<Integer> c = new A<Integer>();
A<Integer> d = new A<Integer>();
A<Integer> e = new A<Integer>();
test(a,b,c,d,e);
}
}
2、the constraint has the form A == F
If F = Tj, then the constraint Tj = A is implied.
If F = U
[]where the type U involves Tj, then if A is an array type V[], or a type variable with an upper bound that is an array type V[], where V is a reference type, this algorithm is applied recursively to the constraint V = U.If the array types U
[]and V[]are the same, their component types must be the same.If F has the form G
<..., Yk-1, U, Yk+1, ...>, where U is type expression that involves Tj, then if A is of the form G<..., Xk-1, V, Xk+1,...>where V is a type expression, this algorithm is applied recursively to the constraint V = U.If F has the form G
<..., Yk-1,?extendsU, Yk+1, ...>, where U involves Tj, then if A is one of:G
<..., Xk-1,?extendsV, Xk+1, ...>. Then this algorithm is applied recursively to the constraint V = U.Otherwise, no constraint is implied on Tj.
If F has the form G
<..., Yk-1,?superU, Yk+1 ,...>, where U involves Tj, then if A is one of:G
<..., Xk-1,?superV, Xk+1, ...>. Then this algorithm is applied recursively to the constraint V = U.Otherwise, no constraint is implied on Tj.
Otherwise, no constraint is implied on Tj.
3、the constraint has the form A >> F
If F = Tj, then the constraint Tj
<:A is implied.We do not make use of such constraints in the main body of the inference algorithm. However, they are used in §15.12.2.8.
If F = U
[], where the type U involves Tj, then if A is an array type V[], or a type variable with an upper bound that is an array type V[], where V is a reference type, this algorithm is applied recursively to the constraint V >> U. Otherwise, no constraint is implied on Tj.This follows from the covariant subtype relation among array types. The constraint A >> F in this case means that A >> U
[]. A is therefore necessarily an array type V[], or a type variable whose upper bound is an array type V[]- otherwise the relation A >> U[]could never hold true. It follows that V[]>> U[]. Since array subtyping is covariant, it must be the case that V >> U.If F has the form G
<..., Yk-1, U, Yk+1, ...>, where U is a type expression that involves Tj, then:If A is an instance of a non-generic type, then no constraint is implied on Tj.
In this case (once again restricting the analysis to the unary case), we have the constraint A >> F = G
<U>. A must be a supertype of the generic type G. However, since A is not a parameterized type, it cannot depend upon the type argument U in any way. It is a supertype of G<X>for every X that is a valid type argument to G. No meaningful constraint on Ucan be derived from A.If A is an invocation of a generic type declaration H, where H is either G or superclass or superinterface of G, then:
If H ≠ G, then let S1, ..., Sn be the type parameters of G, and let H
<U1, ..., Ul>be the unique invocation of H that is a supertype of G<S1, ..., Sn>, and let V = H<U1, ..., Ul>[Sk=U]. Then, if V:>F this algorithm is applied recursively to the constraint A >> V.Our goal here is to simplify the relationship between A and F. We aim to recursively invoke the algorithm on a simpler case, where the type argument is known to be an invocation of the same generic type declaration as the formal.
Let's consider the case where both H and G have only a single type argument. Since we have the constraint A = H
<X>>> F = G<U>, where H is distinct from G, it must be the case that H is some proper superclass or superinterface of G. There must be a (non-wildcard) invocation of H that is a supertype of F = G<U>. Call this invocation V.If we replace F by V in the constraint, we will have accomplished the goal of relating two invocations of the same generic (as it happens, H).
How do we compute V? The declaration of G must introduce a type parameter S, and there must be some (non-wildcard) invocation of H, H
<U1>, that is a supertype of G<S>. Substituting the type expression U for S will then yield a (non-wildcard) invocation of H, H<U1>[S=U], that is a supertype of G<U>. For example, in the simplest instance, U1might be S, in which case we have G<S><:H<S>, and G<U><:H<U>= H<S>[S=U]= V.It may be the case that H
<U1>is independent of S - that is, S does not occur in U1 at all. However, the substitution described above is still valid - in this situation, V = H<U1>[S=U]= H<U1>. Furthermore, in this circumstance, G<T><:H<U1>for any T, and in particular G<U><:H<U1>= V.Regardless of whether U1 depends on S, we have determined the type V, the invocation of H that is a supertype of G
<U>. We can now invoke the algorithm recursively on the constraint H<X>= A >> V = H<U1>[S=U]. We will then be able to relate the type arguments of both invocations of H and extract the relevant constraints from them.Otherwise, if A is of the form G
<..., Xk-1, W, Xk+1, ...>, where W is a type expression, this algorithm is applied recursively to the constraint W = U.We have A = G
<W>>> F = G<U>for some type expression W. Since W is a type expression (and not a wildcard type argument), it must be the case that W = U, by the invariance of parameterized types.Otherwise, if A is of the form G
<..., Xk-1,?extendsW, Xk+1, ...>, this algorithm is applied recursively to the constraint W >> U.We have A = G
<?extendsW>>> F = G<U>for some type expression W. It must be the case that W >> U, by the subtyping rules for wildcard types.Otherwise, if A is of the form G
<..., Xk-1,?superW, Xk+1, ...>, this algorithm is applied recursively to the constraint W << U.We have A = G
<?superW>>> F = G<U>for some type expression W. It must be the case that W << U, by the subtyping rules for wildcard types.Otherwise, no constraint is implied on Tj.
If F has the form G
<..., Yk-1,?extendsU, Yk+1, ...>, where U is a type expression that involves Tj, then:If A is an instance of a non-generic type, then no constraint is implied on Tj.
Once again restricting the analysis to the unary case, we have the constraint A >> F = G
<?extendsU>. A must be a supertype of the generic type G. However, since A is not a parameterized type, it cannot depend upon U in any way. It is a supertype of the type G<?extendsX>for every X such that?extendsX is a valid type argument to G. No meaningful constraint on U can be derived from A.If A is an invocation of a generic type declaration H, where H is either G or superclass or superinterface of G, then:
If H ≠ G, then let S1, ..., Sn be the type parameters of G, and let H
<U1, ..., Ul>be the unique invocation of H that is a supertype of G<S1, ..., Sn>, and let V = H<?extendsU1, ...,?extendsUl>[Sk=U]. Then this algorithm is applied recursively to the constraint A >> V.Our goal here is once more to simplify the relationship between A and F, and recursively invoke the algorithm on a simpler case, where the type argument is known to be an invocation of the same generic type as the formal.
Assume both H and G have only a single type argument. Since we have the constraint A = H
<X>>> F = G<?extendsU>, where H is distinct from G, it must be the case that His some proper superclass or superinterface of G. There must be an invocation of H<Y>, such that H<X>>> H<Y>, that we can use instead of F = G<?extendsU>.How do we compute H
<Y>? As before, note that the declaration of G must introduce a type parameter S, and there must be some (non-wildcard) invocation of H, H<U1>, that is a supertype of G<S>. However, substituting?extendsU for S is not generally valid. To see this, assume U1 = T[].Instead, we produce an invocation of H, H
<?extendsU1>[S=U]. In the simplest instance, U1 might be S, in which case we have G<S><:H<S>, and G<?extendsU><:H<?extendsU>= H<?extendsS>[S=U]= V.Otherwise, if A is of the form G
<..., Xk-1,?extendsW, Xk+1, ...>, this algorithm is applied recursively to the constraint W >> U.We have A = G
<?extendsW>>> F = G<?extendsU>for some type expression W. By the subtyping rules for wildcards it must be the case that W >> U.Otherwise, no constraint is implied on Tj.
If F has the form G
<..., Yk-1,?superU, Yk+1, ...>, where U is a type expression that involves Tj, then A is either:If A is an instance of a non-generic type, then no constraint is implied on Tj.
Restricting the analysis to the unary case, we have the constraint A >> F = G
<?superU>. A must be a supertype of the generic type G. However, since A is not a parameterized type, it cannot depend upon U in any way. It is a supertype of the type G<?superX>for every X such that?superX is a valid type argument to G. No meaningful constraint on Ucan be derived from A.If A is an invocation of a generic type declaration H, where H is either G or superclass or superinterface of G, then:
If H ≠ G, then let S1, ..., Sn be the type parameters of G, and let H
<U1, ..., Ul>be the unique invocation of H that is a supertype of G<S1, ..., Sn>, and let V = H<?superU1, ...,?superUl>[Sk=U]. Then this algorithm is applied recursively to the constraint A >> V.The treatment here is analogous to the case where A = G
<?extendsU>. Here our example would produce an invocation H<?superU1>[S=U].Otherwise, if A is of the form G
<..., Xk-1,?superW, ..., Xk+1, ...>, this algorithm is applied recursively to the constraint W << U.We have A = G
<?superW>>> F = G<?superU>for some type expression W. It must be the case that W << U, by the subtyping rules for wildcard types.Otherwise, no constraint is implied on Tj.
javac之Inferring Type Arguments Based on Actual Arguments的更多相关文章
- [GraphQL] Filter Data Based on Query Arguments with GraphQL
With GraphQL, every field and nested object can have a set of arguments which can be used to request ...
- ERROR: HHH000091: Expected type: java.sql.Timestamp, actual value: java.lang.Integer
在将MySql的数据对应到Java的实体类的时候, 遇到了错误 关键点: Hibernate从mysql数据库查出来的Timestamp类型的数据, 会被Hibernate(或者是数据库连接池Drui ...
- Run Configurations(Debug Configurations)->Arguments里填写program arguments和VM arguments
如图: 1.program arguments存储在String[] args里 2.VM arguments设置的是虚拟机的属性,是传给java虚拟机的.KV形式存储的,是可以通过System.ge ...
- Javac之关于方法的调用1
方法的调用从Attr类的visitApply()方法进入,如下: /** Visitor method for method invocations. * NOTE: The method part ...
- Javac之关于方法的选择
15.12. Method Invocation Expressions 15.12.1. Compile-Time Step 1: Determine Class or Interface to S ...
- javac之Method Invocation Expressions
15.12.1. Compile-Time Step 1: Determine Class or Interface to Search 15.12.2. Compile-Time Step 2: D ...
- 阅读The Java® Language Specification需要知道的术语
Null Pointer Exception,简称NPE 在java中,static final修饰的是常量.根据编译器的不同行为,常量又可分为编译时常量和运行时常量. 举例说明吧 public st ...
- parameters arguments 形式参数 实际参数
parameter和argument的区别 – 笑遍世界 http://smilejay.com/2011/11/parameter_argument/ https://en.wikipedia.or ...
- Spock - Document -04- Interaction Based Testing
Interaction Based Testing Peter Niederwieser, The Spock Framework TeamVersion 1.1 Interaction-based ...
随机推荐
- Selenium2+python自动化之读取Excel数据(xlrd)
前言 当登录的账号有多个的时候,我们一般用excel存放测试数据,本节课介绍,python读取excel方法,并保存为字典格式. 一.环境准备 1.先安装xlrd模块,打开cmd,输入pip inst ...
- jersey学习笔记
最近一个项目用到了jersey,我只是负责前端.也借此机会好好了解一下REST webservice及一大推名词. http://redhacker.iteye.com/blog/1914105 1. ...
- windows7,windows8 64位系统 IIS7.0配置.net网站时报错:未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序。
背景: 在64位的操作系统中, IIS7.0配置.net网站时报错:未能加载文件或程序集“XXX”或它的某一个依赖项.试图加载格式不正确的程序. 解决办法: 把iis 对应的应用程序池 --高级设置- ...
- The Activities of September
- [ACM_动态规划] UVA 12511 Virus [最长公共递增子序列 LCIS 动态规划]
Virus We have a log file, which is a sequence of recorded events. Naturally, the timestamps are s ...
- 万恶的KPI、新兴的OKR及让人纠结的程序员考核
最近两天在研究研发部门如何进行绩效管理(其实一直都在思考,关注,实践,总感觉无从下手,也想求助咨询公司,无奈囊中羞涩).查了两天的资料,主要的方向是KPI,OKR,谷歌等互联网公司的考核方法.这里做个 ...
- JavaScript正则表达式匹配中英文以及常用标点符号白名单写法
我们在编程中经常会遇到特殊字符过滤的问题,今天我们提供一种白名单方式过滤 直接上代码 function RegEXP(s) { var rs = ""; for (var i = ...
- WPF窗口启动时最大化
在xaml对应的后台代码文件的初始化方法中: public ShellView() { InitializeComponent(); #region 启动时串口最大化显示 Rect rc = Syst ...
- 知物由学 | AI时代,那些黑客正在如何打磨他们的“利器”?(一)
本文由 网易云发布. “知物由学”是网易云易盾打造的一个品牌栏目,词语出自汉·王充<论衡·实知>.人,能力有高下之分,学习才知道事物的道理,而后才有智慧,不去求问就不会知道.“知物由学” ...
- C - 前m大的数 (结构体)
点击打开链接 还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小希只想让你把答案中最大的 ...