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. (回文串 Manacher)吉哥系列故事——完美队形II -- hdu -- 4513

    http://acm.hdu.edu.cn/showproblem.php?pid=4513 吉哥系列故事——完美队形II Time Limit: 3000/1000 MS (Java/Others) ...

  2. pytest 常用命令行选项(二)

    本文接上篇继续简介pytest常用的命令行选项. 8.-v(--verbose) 选项 使用-v/--verbose选项,输出的信息会更详细.最明显的区别就是每个文件中的每个测试用例都占一行,测试的名 ...

  3. Billman_ford货币升值——正权回路

    2240和1860那个题目很像啊 都是问货币能不能增多,钻社会制度得空子啊哈哈 唯一不同得是你的起点是任意一个点,这个比较麻烦了,多了一层循环嘞 处理货币名可以用map分配id 然后就是老套的Bill ...

  4. 一个简单 Go Web MVC 框架实现思路

    需要的知识点 为了防止你的心里不适,需要以下知识点: Go 基本知识 Go 反射的深入理解 使用过框架 Go Web 服务器搭建 package main import ( "fmt&quo ...

  5. 抱SQL SERVER大腿之我爱用视图(对大数据量的管理)

    我们拥有一个巨大的表,两千多万条记录.也许在行家眼里,两千多万条记录顶多算条毛,不过这条毛也忒粗壮了一点:我们的数据库占用的空间已经达到5G多了.不要以为是日志文件在搞鬼,日志文件可以自动收缩的,最多 ...

  6. NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(转载)

    原文地址:http://www.cnblogs.com/asxinyu/p/dotnet_Opensource_project_FluentValidation_1.html 阅读目录 1.基本介绍 ...

  7. JQuery fullcalender文档

    转载: http://blog.csdn.net/lgg2011. 使用方式, 引入相关js, css后, $(‘#div_name’).fullCalendar({//options});  接受的 ...

  8. RabbitMQ基础入门篇

    下载安装 Erlang RabbitMQ 启动RabbitMQ管理平台插件 DOS下进入到安装目录\sbin,执行以下命令 rabbitmq-plugins enable rabbitmq_manag ...

  9. Office - Outlook

    将邮件存到本地 服务器容量有限,避免丢失和经常提示容量不足 步骤 在File->Account Settings->Account Settings下面 在Data Files标签页新建一 ...

  10. CRUD组件的高阶使用

    1.list页面自定列显示: class PermissionConfig(sites.AryaConfig):       def dabo(self, obj=None, is_header=Fa ...