我目前正在编写Java编译器并已实现了第15.12.2.7节。 JLS7(http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.7),这是规范中最讨厌的部分之一。我仍然有一个问题,因为规范似乎不明确或模棱两可。我的问题是这一行:
lcta(U)=?如果U的上限是Object,否则?扩展lub(U,Object)
U是任意类型的表达式。类型表达式的上限是多少?另外,为什么lcta总是一个通配符?
规范定义
CandidateInvocation(G)= lci(Inv(G))。
现在,例如,考虑Inv(G)= {List< String> ,即,唯一可能的候选调用是单个参数化类型。现在,由于规则
lci(G< X1,...,Xn>)= G< lcta(X1),...,lcta(Xn)> ,
CandidateInvocation(G)=的结果 lci({List< String>})将被定义为:
列表与LT; LCTA(字符串)>
在我看来,lcta应该只是在这里返回String,因为如果List< String>是唯一可能的调用,推断List< String>是个好主意。作为论点。但是,lcta(U)的定义要求结果是?要么 ?扩展lub(...),因此结果始终是通配符。这看起来很奇怪。我在这里误解了什么?
答案 0 :(得分:6)
这看起来像规范的错误。 JSL3中不存在lcta(U)
的子句。显然,lci(e1..en)
时JLS3对n=1
的定义不完整,新规范试图修复它。但正如你所推断的那样,修复似乎是胡言乱语。
Javac7将lci( { List<String> } )
计算为List<String>
,忽略添加的子句。
这个问题应该提到规范维护者;不知道如何联系他们。您可以尝试使用openjdk compiler-dev 邮件列表;有一些知识渊博的人。
答案 1 :(得分:1)
我已经在compiler-dev邮件列表中询问并收到了答案:
是的,这里的规范是错误的。 lcta(U)的规则只是完全废话:)。此外,他们声称最好不要为一个参数调用lcta(U)并且只使用U(因为单个参数U的最小公共类型参数应该总是U本身)。