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 ...
随机推荐
- hdu 1163 Eddy's digital Roots 【九余数定理】
http://acm.hdu.edu.cn/showproblem.php?pid=1163 九余数定理: 如果一个数的各个数位上的数字之和能被9整除,那么这个数能被9整除:如果一个数各个数位上的数字 ...
- IDEA14添加SVN
今天升级IDEA14,发现SVN变了,折腾了好一会才搞好.记录一下,希望其他人能少走弯路.主要是IDEA14的svn是用命令行工具进行操作,这样对以后SVN的兼容性也会好很多,这个在他们官方的博客上也 ...
- Delphi XE6 Android拨号函数
http://blog.sina.com.cn/s/blog_44fa172f0101rpex.html Delphi XE6 Android拨号函数 (2014-05-07 17:48:51) 转载 ...
- 网友写的解决uniGUI限制的方法
群友写的解决uniGUI试用版限制修改SessionTimeOut,思路很精巧,贴过来分享,感谢朋友的奉献.当然,如果真正用uniGUI实做项目,买份正版是正道! var UniServerOpt ...
- 检测Linux服务器端口是否开通
现如今云服务器已经是大势所趋,国内比较著名的云服务器厂商有阿里.腾讯,国外有aws,尽管有的公司目前为止还是使用的物理机,但是无论你是使用的云服务器还是物理机,在运行服务时都必不可少的需要监听到指定的 ...
- Checkpoint--查看各DB上的脏页
可以使用sys.dm_os_buffer_descriptors来看数据页在buffer pool中的状态,其中is_modified来标示数据页是否为脏页 --------------------- ...
- musql 添加字段语句
修改表tax_version添加up_content属性为text类型非空,注释为“更新内容”,字段添加再“name”属性后面 ALTER TABLE `tax_version` ADD `up_co ...
- Docker容器的原理与实践(上)
本文来自网易云社区. 虚拟化 是一种资源管理技术,将计算机的各种资源予以抽象.转换后呈现出来, 打破实体结构间的不可切割的障碍,使用户可以比原本更好的方式来应用这些资源. Hypervisor 一种运 ...
- kubernetes1.9管中窥豹-CRD概念、使用场景及实例
欢迎访问网易云社区,了解更多网易技术产品运营经验. 前言 默认读者有kubernetes基础概念的背景知识,因此基础概念例如有状态.pod.Replica Sets.Deployments.state ...
- django Form的回顾--手动档和自动挡
from django.shortcuts import renderfrom django.forms import Formfrom django.forms import fieldsfro ...