Javac之glb与lub
5.1.10. Capture Conversion
Let G name a generic type declaration (§8.1.2, §9.1.2) with n type parameters A1,...,An with corresponding bounds U1,...,Un.
There exists a capture conversion from a parameterized type G<T1,...,Tn> (§4.5) to a parameterized type G<S1,...,Sn>, where, for 1 ≤ i ≤ n :
If Ti is a wildcard type argument (§4.5.1) of the form
?, then Si is a fresh type variable whose upper bound is Ui[A1:=S1,...,An:=Sn]and whose lower bound is the null type (§4.1).If Ti is a wildcard type argument of the form
?extendsBi, then Si is a fresh type variable whose upper bound is glb(Bi, Ui[A1:=S1,...,An:=Sn]) and whose lower bound is the null type.glb(V1,...,Vm) is defined as V1
&...&Vm.It is a compile-time error if, for any two classes (not interfaces) Vi and Vj, Vi is not a subclass of Vj or vice versa.
If Ti is a wildcard type argument of the form
?superBi, then Si is a fresh type variable whose upper bound is Ui[A1:=S1,...,An:=Sn]and whose lower bound is Bi.Otherwise, Si = Ti.
Capture conversion on any type other than a parameterized type (§4.5) acts as an identity conversion (§5.1.1).
Capture conversion is not applied recursively.
就是说在G<T1>到G<S1>的过程中可能T1类型也是T1<X>这样的类型。
Capture conversion never requires a special action at run time and therefore never throws an exception at run time.
4.10.4. Least Upper Bound
| 
 
  | 
 List<String>  | 
 List<Object>  | 
| 
 ST(Ui) the set of supertypes of Ui.  | 
 ST( { 
 
 
 }  | 
 ST( { 
 
 
 }  | 
| 
 EST(Ui) the set of erased supertypes of U  | 
 EST( { 
 
 
 }  | 
 EST( { 
 
 
 }  | 
| 
 EC the intersection of all the sets EST(Ui)  | 
 EC = { 
 
 
 }  | 
|
| 
 MEC the minimal erased candidate set for U1 ... Uk  | 
 MEC = { 
 }  | 
|
| 
 Relevant(G) Relevant(G) = { V | 1≤i≤k: V in ST(Ui) and V=G }  | 
 Relevant( { 
 
 } 
  | 
|
The least upper bound, or "lub", of a set of reference types is a shared supertype that is more specific than any other shared supertype (that is, no other shared supertype is a subtype of the least upper bound). This type, lub(U1, ..., Uk), is determined as follows.
If k = 1, then the lub is the type itself: lub(U) = U.
Otherwise:
For each Ui (1 ≤ i ≤ k):
Let ST(Ui) be the set of supertypes of Ui.
Let EST(Ui), the set of erased supertypes of Ui, be:
EST(Ui) = { |W| | W in ST(Ui) } where |W| is the erasure of W.
The reason for computing the set of erased supertypes is to deal with situations where the set of types includes several distinct parameterizations of a generic type.
For example, given
Listand<String>List, simply intersecting the sets ST(<Object>List) = {<String>List,<String>Collection,<String>Object} and ST(List) = {<Object>List,<Object>Collection,<Object>Object} would yield a set {Object}, and we would have lost track of the fact that the upper bound can safely be assumed to be aList.In contrast, intersecting EST(
List) = {<String>List,Collection,Object} and EST(List) = {<Object>List,Collection,Object} yields {List,Collection,Object}, which will eventually enable us to produceList.<?>Let EC, the erased candidate set for U1 ... Uk, be the intersection of all the sets EST(Ui) (1 ≤ i ≤ k).
Let MEC, the minimal erased candidate set for U1 ... Uk, be:
MEC = { V | V in EC, and for all W ≠ V in EC, it is not the case that W
<:V }Because we are seeking to infer more precise types, we wish to filter out any candidates that are supertypes of other candidates. This is what computing MEC accomplishes. In our running example, we had EC = {
List,Collection,Object}, so MEC = {List}. The next step is to recover type arguments for the erased types in MEC.For any element G of MEC that is a generic type:
Let the "relevant" parameterizations of G, Relevant(G), be:
Relevant(G) = { V | 1 ≤ i ≤ k: V in ST(Ui) and V = G
<...>}In our running example, the only generic element of MEC is
List, and Relevant(List) = {List,<String>List}. We will now seek to find a type argument for<Object>Listthat contains (§4.5.1) bothStringandObject.This is done by means of the least containing parameterization (lcp) operation defined below. The first line defines lcp() on a set, such as Relevant(
List), as an operation on a list of the elements of the set. The next line defines the operation on such lists, as a pairwise reduction on the elements of the list. The third line is the definition of lcp() on pairs of parameterized types, which in turn relies on the notion of least containing type argument (lcta). lcta() is defined for all possible cases.Let the "candidate" parameterization of G, Candidate(G), be the most specific parameterization of the generic type G that contains all the relevant parameterizations of G:
Candidate(G) = lcp(Relevant(G)) // Relevant(G)经过lcp运算后就会得到the most specific parameterization of the generic type G
where lcp(), the least containing invocation, is:
lcp(S) = lcp(
e1, ...,en) whereei(1 ≤ i ≤ n) in S // 第一行定义了lcp()lcp(
e1, ...,en) = lcp(lcp(e1,e2),e3, ...,en) // 第二行两两来减少列表中的元素lcp(G
<X1, ..., Xn>, G<Y1, ..., Yn>) = G<lcta(X1, Y1), ..., lcta(Xn, Yn)> // 依赖lcta进行操作,lcta列举出了两个元素的所有情况lcp(G
<X1, ..., Xn>) = G<lcta(X1), ..., lcta(Xn)>
and where lcta(), the least containing type argument, is: (assuming U and V are types)
lcta(U, V) = U if U = V, otherwise
?extendslub(U, V)lcta(U,
?extendsV) =?extendslub(U, V)lcta(U,
?superV) =?superglb(U, V)lcta(
?extendsU,?extendsV) =?extendslub(U, V)lcta(
?extendsU,?superV) = U if U = V, otherwise?lcta(
?superU,?superV) =?superglb(U, V)lcta(U) =
?if U's upper bound isObject, otherwise?extendslub(U,Object)
and where glb() is as defined in §5.1.10.
Let lub(U1 ... Uk) be:
Best(W1)
&...&Best(Wr)where Wi (1 ≤ i ≤ r) are the elements of MEC, the minimal erased candidate set of U1 ... Uk;
and where, if any of these elements are generic, we use the candidate parameterization (so as to recover type arguments):
Best(X) = Candidate(X) if X is generic; X otherwise.
Strictly speaking, this lub() function only approximates a least upper bound. Formally, there may exist some other type T such that all of U1 ... Uk are subtypes of T and T is a subtype of lub(U1, ..., Uk). However, a compiler for the Java programming language must implement lub() as specified above.
It is possible that the lub() function yields an infinite type. This is permissible, and a compiler for the Java programming language must recognize such situations and represent them appropriately using cyclic data structures.
The possibility of an infinite type stems from the recursive calls to lub(). Readers familiar with recursive types should note that an infinite type is not the same as a recursive type.
The declared type of an exception parameter that denotes its type as a union with alternatives D1 | D2 | ... | Dn is lub(D1, D2, ..., Dn) (§15.12.2.7).
参考:https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20
参考:
(1)https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html
(2)https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.10
Javac之glb与lub的更多相关文章
- Fedora javac 命令提示 [javac: 未找到命令...]
		
[joy@localhost ~]$ java -version openjdk version "1.8.0_91" OpenJDK Runtime Environment (b ...
 - javac -encoding utf8 in linux
		
由于另外负责编码的同事用的是utf-8,我用的默认的编码格式gbk,在提交代码时,为了迁就他,我打算把格式用工具转成utf-8. 转化成果后,然后在make一下,发现javac -encoding u ...
 - javac编译不同目录的源码提示找不到符号
		
对于单个文件的且不引用其他类文件的java源码用javac编译大家都很熟悉即 javac mycode.java 但是如果这个文件引用到了其他的类文件,在进行编译的时候就会提示找不到符号,这时我们需要 ...
 - JAVA安装过程中出现的“javac不是内部或外部指令”的解决方法
		
近来重新安装了JAVA,安装过程中出现问题,网上找到解决办法,汇总发布. 解决流程: 1.确定自己的环境变量设置没问题,没有出现遗漏 : . 等情况 (具体环境变量设置百度) 2.环境变量设置后 ,d ...
 - java与javac命令的功用
		
一.javac用来编译java程序,比如说我写了一个Server.java文件,首先通过命令行进入.java文件所在的路径, 然后通过输入 javac Server.java 命令行来完成编译,编译之 ...
 - Maven打包  报 Unable to locate the Javac Compiler in:   C:\Program Files\Java\jre1.8.0_73\..\lib\tools.jar
		
无法找到javac 编译环境 右键项目 --> properties -->Java Build Path -->选中JRE 点击右侧 Edit 编辑 --> 把你设置的JRE ...
 - eclipse中的javac命令与java命令
		
一.eclipse的javac命令:当eclipse对.java(源文件)文件进行保存操作时(快捷键ctrl+s),会执行javac命令.见上图,Default output folder(默认输出文 ...
 - 配置javac环境
		
初始的javac是默认不可用,如下图: 系统变量->新建->变量名:JAVA_HOME 变量值:(C:\Program Files\Java\jdk1.7.0_03)(这只是我的JDK安装 ...
 - javac 导入第三方jar包
		
如果是导入一个包,只需要 javac -classpath xxx/xxx/xxx.jar xxx.java 即可 如果有多个包,windows下用分号隔开,Lunix下用冒号隔开即可.
 
随机推荐
- <a href=“#”>
			
在html中看到这样的属性:<a href=“#”>搜了好久,感觉不甚明白,现记之,等遇到了再做补充. # is called an anchor (or hash...). so the ...
 - cmake检测g++编译器是否支持c++11
			
# 相关链接:https://cmake.org/cmake/help/v3.0/module/CheckCXXCompilerFlag.htmlinclude(CheckCXXCompilerF ...
 - PrefixHeader.pch  在工程中的使用
			
1) 新建一个pch文件 2) 在 工程 Build Settings 中搜索 header 将Precompile Prefix Header 置为YES 2) 选中pch文件, 将右侧相对路径 ...
 - python 的几种启动方式
			
python 的几种启动方式 (1)利用Win的操作系统的:命令行工具 cmd.exe Win + R 调出运行对话框,然后输入cmd,即可调出“命令提示符对话框” 或者 在菜单中店家附件中的命令提 ...
 - Lucene原理一
			
Lucene 是一个高效的,基于Java 的全文检索库. 所以在了解Lucene之前要费一番工夫了解一下全文检索. 那么什么叫做全文检索呢?这要从我们生活中的数据说起. 我们生活中的数据总体分为两种: ...
 - nodejs 获取文件的编码方式
			
使用nodejs获取文件夹内文件的编码方式:使用jschardet模块. 下面的代码还有问题,没有添加结束的语句,没有判断应该在哪执行res.send(). res.send()不能放在forEach ...
 - JS代码指导原则
			
一.什么是平稳退化? 如果含有JS代码的网页在用户浏览器不支持JS(或者禁用JS)时,用户仍然能够顺利浏览(网站功能正常,只是视觉效果可能差一些),那么这个网页就能够平稳退化 网页能够平稳退化是很必要 ...
 - ASP.NET关于Session_End触发与否的问题
			
项目背景: 要求开发一个篆文识别网站,由于之前做好了WinForm的,把系统直接移植到WebForm上就好.工作比较简单,但确实遇到不少问题. 核心问题是: 篆文识别涉及到用户对原始图片的预处理(例如 ...
 - Dalsa线扫相机配置-一台工控机同时连接多个GigE相机
			
如图,我强悍的工控机,有六个网口. 实际用的时候连了多台相机,为了偷懒我就把六个网口的地址分别设为192.168.0.1~192.168.0.6,以为相机的IP只要设在192.168.0这个网段然后随 ...
 - 关于Git bash 在win10重装系统情况下闪退并生成mintty.exe.stackdump文件的问题
			
问题内容:在重装win10系统情况下,有可能会出现安装Git后右击Git bash会出现闪退并生成mintty.exe.stackdump文件 个人解决方案:查看网络上各位网友的意见和解决方法后,自己 ...