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. PHP数据库抽象层--PDO(PHP Data Object) [一]

    1.简介:(PDO数据库访问抽象层,统一各种 数据库的访问接口 ) PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口.实现 PDO 接口的每个数据库驱动可以公开具体数据库 ...

  2. (匹配)Fire Net --hdu --1045

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1045 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  3. oracle中row_number() over()分析函数用法

    row_number()over(partition by col1 order by col2)表示根据col1分组,在分组内部根据col2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内 ...

  4. ggdl

    \documentclass{article} \usepackage{geometry} \geometry{hmargin=1cm,vmargin=1cm} \usepackage{tikz} % ...

  5. Android-卖票案例static-不推荐此方式

    需求描述:四个窗口一起卖票,把10张票卖完,不许多卖 先看一个错误的案例: package android.java.thread06; /** * 售票线程 */ class Booking ext ...

  6. 查看Linux服务器被映射的公网ip

    查看Linux服务器被映射的公网ip   现在云服务器非常流行,不仅企业甚至是个人都可能拥有自己的云服务器,但是目前的云服务器厂商提供的公网IP大都是映射而来,所以在Linux服务器上执行ifconf ...

  7. 利用backtrace和backtrace_symbols函数打印调用栈信息

    在头文件"execinfo.h"中声明了三个函数用于获取当前线程的函数调用堆栈. #include <execinfo.h>  int backtrace(void * ...

  8. TSQL--删除登陆相关的用户

    无二话,上代码 --删除登陆相关的用户 --遍历所有数据库,查找到与登录名相关联的的用户,生成删除脚本 ) SET @loginName='DBA'; DECLARE @comm NVARCHAR(M ...

  9. 解决oninput在输入中文时,会获取拼音的问题

    (1)起因:在今天做项目测试的时候发现的问题,在用微软自带的输入法的时候,输入中文,文本框会获得拼音 如图所示: (2)解决办法:经过一段时间的百度查找,最后通过这篇文章找到了解决的方法,这里给出网址 ...

  10. ModelForm错误验证自定义钩子和全局钩子

    当需要对model_class中字段作进一步验证,作进一步的约束时,需要使用到钩子,即claan_xxx和clean方法.其返回的errors有点不是那么好处理.看示例.   1.Model_clas ...