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? extends U, 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<? extends U>. 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<? extends V>, or G<? super V>. 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<? extends U>. The rules of subtyping for wildcards imply that V << U.

    • G<..., Xk-1? extends V, Xk+1, ...>. Then this algorithm is applied recursively to the constraint V << U.

      Extending the analysis above, we have A = G<? extends V> << G<? extends U>. The rules of subtyping for wildcards again imply that V << U.

    • Otherwise, no constraint is implied on Tj.

      Here, we have A = G<? super V> << G<? extends U>. 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 be Object, 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? super U, 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<? super U>. 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<? super V>. 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<? super U>. The rules of subtyping for wildcards imply that V >> U.

    • G<..., Xk-1? super V, Xk+1, ...>. Then this algorithm is applied recursively to the constraint V >> U.

      We have A = G<? super V> << G<? super U>. 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<? extends V> << G<? super U>. 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? extends U, Yk+1, ...>, where U involves Tj, then if A is one of:

    • G<..., Xk-1? extends V, 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? super U, Yk+1 ,...>, where U involves Tj, then if A is one of:

    • G<..., Xk-1? super V, 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? extends W, Xk+1, ...>, this algorithm is applied recursively to the constraint W >> U.

        We have A = G<? extends W> >> 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? super W, Xk+1, ...>, this algorithm is applied recursively to the constraint W << U.

        We have A = G<? super W> >> 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? extends 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.

      Once again restricting the analysis to the unary case, we have the constraint A >> F = G<? extends U>. 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<? extends X> for every X such that ? extends X 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<? extends U1, ..., ? extends Ul>[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<? extends U>, 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<? extends U>.

        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 ? extends U for S is not generally valid. To see this, assume U1 = T[].

        Instead, we produce an invocation of H, H<? extends U1>[S=U]. In the simplest instance, U1 might be S, in which case we have G<S> <: H<S>, and G<? extends U> <: H<?extends U> = H<? extends S>[S=U] = V.

      • Otherwise, if A is of the form G<..., Xk-1? extends W, Xk+1, ...>, this algorithm is applied recursively to the constraint W >> U.

        We have A = G<? extends W> >> F = G<? extends U> 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? super U, 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<? super U>. 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<? super X> for every X such that ? super X 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<? super U1, ..., ? super Ul>[Sk=U]. Then this algorithm is applied recursively to the constraint A >> V.

        The treatment here is analogous to the case where A = G<? extends U>. Here our example would produce an invocation H<? super U1>[S=U].

      • Otherwise, if A is of the form G<..., Xk-1? super W, ..., Xk+1, ...>, this algorithm is applied recursively to the constraint W << U.

        We have A = G<? super W> >> F = G<? super 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.

javac之Inferring Type Arguments Based on Actual Arguments的更多相关文章

  1. [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 ...

  2. ERROR: HHH000091: Expected type: java.sql.Timestamp, actual value: java.lang.Integer

    在将MySql的数据对应到Java的实体类的时候, 遇到了错误 关键点: Hibernate从mysql数据库查出来的Timestamp类型的数据, 会被Hibernate(或者是数据库连接池Drui ...

  3. Run Configurations(Debug Configurations)->Arguments里填写program arguments和VM arguments

    如图: 1.program arguments存储在String[] args里 2.VM arguments设置的是虚拟机的属性,是传给java虚拟机的.KV形式存储的,是可以通过System.ge ...

  4. Javac之关于方法的调用1

    方法的调用从Attr类的visitApply()方法进入,如下: /** Visitor method for method invocations. * NOTE: The method part ...

  5. Javac之关于方法的选择

    15.12. Method Invocation Expressions 15.12.1. Compile-Time Step 1: Determine Class or Interface to S ...

  6. 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 ...

  7. 阅读The Java® Language Specification需要知道的术语

    Null Pointer Exception,简称NPE 在java中,static final修饰的是常量.根据编译器的不同行为,常量又可分为编译时常量和运行时常量. 举例说明吧 public st ...

  8. parameters arguments 形式参数 实际参数

    parameter和argument的区别 – 笑遍世界 http://smilejay.com/2011/11/parameter_argument/ https://en.wikipedia.or ...

  9. Spock - Document -04- Interaction Based Testing

    Interaction Based Testing Peter Niederwieser, The Spock Framework TeamVersion 1.1 Interaction-based ...

随机推荐

  1. hdu 1163 Eddy's digital Roots 【九余数定理】

    http://acm.hdu.edu.cn/showproblem.php?pid=1163 九余数定理: 如果一个数的各个数位上的数字之和能被9整除,那么这个数能被9整除:如果一个数各个数位上的数字 ...

  2. IDEA14添加SVN

    今天升级IDEA14,发现SVN变了,折腾了好一会才搞好.记录一下,希望其他人能少走弯路.主要是IDEA14的svn是用命令行工具进行操作,这样对以后SVN的兼容性也会好很多,这个在他们官方的博客上也 ...

  3. Delphi XE6 Android拨号函数

    http://blog.sina.com.cn/s/blog_44fa172f0101rpex.html Delphi XE6 Android拨号函数 (2014-05-07 17:48:51) 转载 ...

  4. 网友写的解决uniGUI限制的方法

    群友写的解决uniGUI试用版限制修改SessionTimeOut,思路很精巧,贴过来分享,感谢朋友的奉献.当然,如果真正用uniGUI实做项目,买份正版是正道! var   UniServerOpt ...

  5. 检测Linux服务器端口是否开通

    现如今云服务器已经是大势所趋,国内比较著名的云服务器厂商有阿里.腾讯,国外有aws,尽管有的公司目前为止还是使用的物理机,但是无论你是使用的云服务器还是物理机,在运行服务时都必不可少的需要监听到指定的 ...

  6. Checkpoint--查看各DB上的脏页

    可以使用sys.dm_os_buffer_descriptors来看数据页在buffer pool中的状态,其中is_modified来标示数据页是否为脏页 --------------------- ...

  7. musql 添加字段语句

    修改表tax_version添加up_content属性为text类型非空,注释为“更新内容”,字段添加再“name”属性后面 ALTER TABLE `tax_version` ADD `up_co ...

  8. Docker容器的原理与实践(上)

    本文来自网易云社区. 虚拟化 是一种资源管理技术,将计算机的各种资源予以抽象.转换后呈现出来, 打破实体结构间的不可切割的障碍,使用户可以比原本更好的方式来应用这些资源. Hypervisor 一种运 ...

  9. kubernetes1.9管中窥豹-CRD概念、使用场景及实例

    欢迎访问网易云社区,了解更多网易技术产品运营经验. 前言 默认读者有kubernetes基础概念的背景知识,因此基础概念例如有状态.pod.Replica Sets.Deployments.state ...

  10. django Form的回顾--手动档和自动挡

      from django.shortcuts import renderfrom django.forms import Formfrom django.forms import fieldsfro ...