问题标签 [jls]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - Java 铸造:是编译器错了,还是语言规范错了,还是我错了?
我一直在阅读 Java 语言规范,第 3 版,并发现我认为规范和 javac 编译器实现之间存在差异。Eclipse 编译器中也存在相同的差异。
第15.16节讨论了强制转换表达式。它说如果参数类型无法通过强制转换转换为强制类型转换(第 5.5 节),则应该是编译时错误:
如果操作数的编译时类型可能永远不会根据强制转换规则(第 5.5 节)强制转换为强制转换运算符指定的类型,则这是一个编译时错误。否则,在运行时,操作数的值会通过强制转换为强制转换运算符指定的类型进行转换(如有必要)。
第5.5节讨论了强制转换。它给出了允许的转换类型列表。列表中特别缺少的是“拆箱转换,然后是扩大/缩小原始转换”。然而,javac 编译器(以及 Eclipse 编译器)似乎确实允许这种确切的转换顺序。例如:
...编译得很好。(有问题的转换是转换为long
; 参数是 type java.lang.Integer
,因此转换需要取消装箱,int
然后是扩大的原始转换)。
同样,根据 JLS,应该不可能转换 from byte
to char
,因为(根据5.1.4)需要扩大原始转换和缩小原始转换 - 但是,编译器也允许这种转换。
任何人都可以启发我吗?
编辑:因为问这个,我已经向 Oracle 提交了一个错误报告。他们的回应是,这是“JLS 中的一个小故障”。
java - Java 语言规范第 4 版何时可用?
既然 JDK 7 开发人员预览版已经发布,人们可能会认为是时候推出新的 JLS。毕竟,语言已经发生了变化,尽管很小。
我还没有找到任何东西。什么时候可以使用新的 JLS,从哪里可以获得它?
eclipse - 是 eclipse 还是 maven-compiler-plugin 错误,泛型类转换问题?
我有这样的代码:
我在 TestCase 类中使用:
此代码在 eclipse 中给出警告:
类是原始类型。对泛型类的引用应该被参数化
和
此行有多个标记
- 类型安全:MyClass 类型的通用方法 doSomething(String, Class) 的未经检查的调用 doSomething(String, Class)
- 类型安全:Class 类型的表达式需要未经检查的转换以符合 Class
当我在 Eclipse 中运行此代码(测试)时 - 一切正常。当我通过命令提示符通过“mvn clean install”执行此操作时,我得到:
C:\pathToProject\src\test\java\packagesPath\MyTestCase.java:[xx,xxx] 发现不兼容的类型:
java.lang.Object
required: com.somePackagePath.MyClass
但是在提供时:
我没有收到任何错误或警告。.
我知道 java 编译器会删除类型 info,所以:
eclipse 不应该提供编译器错误而不是警告,还是 maven-plugin-compiler 造成问题?
maven插件是:
亲切的问候,
暴君
java - JVM 在加载特定类时会加载所有使用的类吗?
当 JVM 加载一个类 A 时,它会加载 A 中使用的所有类吗?
我想知道进口声明是否对加载过程很重要?
到 JLS 的链接将不胜感激。
java - Java:编译时解析和“最具体的方法”,因为它适用于变量arity
有人可以帮我理解JLS re: most specific method 的第 15.12.2.5 节吗?
(来自 JLS 的大棒剪切和粘贴如下)
此外,一个名为 m 的变量 arity 成员方法比另一个同名的变量 arity 成员方法更具体,如果:
- 一个成员方法有 n 个参数,另一个有 k 个参数,其中 n >= k。第一个成员方法的参数类型为 T1, 。. . , Tn-1 , Tn[], 其他方法的参数类型为 U1, . . . , Uk-1, Uk[]。如果第二种方法是泛型的,则令 R1 ... Rp p1 为其形式类型参数,令 Bl 为 Rl、1lp 的声明边界,令 A1 ... Ap 为推断的实际类型参数(第 15.12.2.7 节)对于初始约束下的此调用 Ti << Ui,1ik-1, Ti << Uk, kin 并让 Si = Ui[R1 = A1, ..., Rp = Ap] 1ik; 否则令 Si = Ui, 1ik。则:对于从 1 到 k-1 的所有 j,Tj <: Sj,并且,对于从 k 到 n 的所有 j,Tj <: Sk,并且,如果第二种方法是如上所述的通用方法,则 Al <: Bl [R1 = A1,...,Rp = Ap],1lp。
- 一个成员方法有 k 个参数,另一个有 n 个参数,其中 n >= k。第一种方法的参数类型为 U1, . . . , Uk-1, Uk[], 其他方法的参数类型为 T1, . . ., Tn-1, Tn[]。如果第二种方法是泛型的,则令 R1 ... Rp p1 为其形式类型参数,令 Bl 为 Rl、1lp 的声明边界,令 A1 ... Ap 为推断的实际类型参数(第 15.12.2.7 节)对于初始约束下的此调用 Ui << Ti, 1ik-1, Uk << Ti, kin 并让 Si = Ti[R1 = A1, ..., Rp = Ap] 1in; 否则令 Si = Ti, 1in。然后:对于从 1 到 k-1 的所有 j,Uj <: Sj,并且对于从 k 到 n 的所有 j,Uk <: Sj,并且,如果第二种方法是如上所述的通用方法,则 Al <: Bl [R1 = A1,...,Rp = Ap],1lp。
忽略泛型问题,这是否意味着在决定一种方法是否比另一种方法更具体时,可变参数比子类型更重要,或者子类型比可变参数更重要?我想不通。
具体示例:compute()
根据 JLS,以下哪种方法“更具体”?
我不知道哪个“更具体”;输出打印
我很困惑如何解释结果。当第一个参数是字符串时,编译器会选择具有更具体子类型的方法。当第一个参数是一个对象时,编译器选择具有较少数量的可选可变参数的方法。
注意:如果您没有阅读 JLS 的这一部分,并且您给出的答案取决于参数的类型,那么您就没有帮助我。如果您仔细阅读 JLS,除了与泛型相关的部分之外,“更具体”的定义取决于声明的参数,而不是实际的参数——这在 JLS 的其他部分(找不到此刻)。
例如,对于固定数量的方法,compute(String s)
将比compute(Object o)
. 但我试图了解 JLS re: variable arity methods 的相关部分。
java - Java:重载方法解析和可变参数——令人困惑的例子
就在我以为我理解JLS15.12应用于可变参数时,下面是这个例子:
打印出来
我理解第一行:JLS15.12说方法解析分阶段进行,阶段 1 和 2 忽略 varargs 方法以找出是否有兼容的方法,只有在阶段 1 和 2 失败时才会发生阶段 3(包括 varargs)。(请参阅 JLS 和这个 SO 问题。)所以如果适用,compute(String s, Object... objects)
总是会被忽略。compute(Object obj1, Object obj2)
但我不明白为什么其他两行打印 43 。AnObject[]
也是 an 的一个实例Object
,那么为什么它匹配 varargs 方法呢?
编辑:
...还有这个
打印42
。
java - Java:编译时解析和“最具体的方法”
如果您尝试在下面使用重载函数compute1()
、compute2()
和 ,则会导致编译错误:compute5()
在阅读了 JLS 第 15.12 节之后,我想我明白了......在匹配重载方法的第 2 阶段(允许装箱/拆箱,没有可变参数)中,在确定“最具体的方法”时,JLS 说(实际上)最特定方法是其形式参数是其他适用方法的子类型的方法,并且原语和对象(例如int
和Integer
)绝不是彼此的子类型。SoInteger
是 的子类型Integer
,并且int
是 的子类型int
,但是Integer
和与int
/r/t 子类型比较不兼容,因此compute1()
/compute2()
对都没有最具体的方法。
(而 incompute3()
和compute4()
带有String
参数的方法比带有参数的方法更具体Object
,所以程序打印 6 和 8。)
我的推理正确吗?
java - Java 泛型类型中的通配符参数在其范围内的形式条件是什么?
使用 Java 中的参数化类型,检查参数是否在其范围内的规则如何完全适用于通配符?
给定这样的类:
尝试编译器接受的内容会了解到:
? extends
允许使用不相关接口类型的通配符:Foo<? extends Runnable>
有效? extends
不允许使用不相关类类型的通配符:Foo<? extends Thread>
无效。这是有道理的,因为没有类型可以是两者的子Number
类型Thread
- 在
? super
通配符中,通配符的下限必须是类型变量边界的子类型:Foo<? super Runnable>
不允许,因为Runnable
不是 的子类型Number
。同样,这个限制非常有意义。
但是这些规则是在哪里定义的?查看Java 语言规范第 4.5 节,我没有看到任何区分接口和类的东西。当应用我对 JLSFoo<? super Runnable>
的解释时,据说是有效的。所以我可能误解了一些东西。这是我的尝试:
从 JLS 的那个部分:
参数化类型由类或接口名称 C 和实际类型参数列表 <T1 , ... , Tn> 组成。如果 C 不是泛型类或接口的名称,或者实际类型实参列表中的类型实参数量与 C 声明的类型实参数量不同,则属于编译时错误。在下文中,无论何时我们说对于类或接口类型,我们也包括泛型版本,除非明确排除。在本节中,让 A1 , ... , An 是 C 的形式类型参数,让 Bi 是 Ai 的声明边界。符号 [Ai := Ti] 表示将类型变量 Ai 替换为类型 Ti,用于 1 <= i <= n,并在整个规范中使用。
令 P = G<T1, ..., Tn> 为参数化类型。必须是这样的情况,在对每个实际类型参数 Xi, 1 <= i <= n 进行捕获转换(第 5.1.10 节)导致类型 G<X1, ..., Xn> 之后, Xi <: Bi[A1 := X1, ..., An := Xn] (§4.10),或发生编译时错误。
将其应用于 P = Foo<? super Runnable>
:给出 C = Foo
, n = 1, T1 =? super Runnable
和 B1 = Number
。
对于捕获转换,这部分捕获转换的定义适用:
如果 Ti 是形式的通配符类型参数?super Bi,则 Si 是一个新类型变量,其上界为 Ui[A1 := S1, ..., An := Sn] ,下界为 Bi。
这给出了 G<X1, ..., Xn> =Foo<X>
其中X
是具有上限Number
和下限的新类型变量Runnable
。我没有看到任何明确禁止这种类型变量的东西。
B1 = 中没有类型变量Number
,所以 Bi[A1 := X1, ..., An := Xn] 仍然是简单Number
的 。
X
具有Number
作为上限(来自捕获转换),并且根据子类型化规则“类型变量的直接超类型是其边界中列出的类型”,所以X
<: Number
(= Bi[A1 := X1, ... , An := Xn]),所以这个参数在它的范围内。(但事实并非如此!)
遵循相同的推理,每个通配符都在其范围内,所以这里有些地方是不对的……但是这个推理到底哪里出错了?这些规则在正确应用时如何运作?
java - 我应该如何阅读 JLS 中的语法说明?
/blockquote>有人可以帮我理解这种语法模式吗?可能意味着什么?
xx: " xxx
opt
"
java - JLS 如何对应 Sun javac / 为什么它们不匹配
在Java中给出了这个:
你可以写
但不能写(给出编译器错误)
错误是
现在在 JLS 第二版中,这可以通过15.26.2 复合赋值运算符中的这一行来解释:
All compound assignment operators require both operands to be of primitive type, except for +=, which allows the right-hand operand to be of any type if the left-hand operand is of type String.
但在 JLS 第三版中,这条评论消失了,关于复合运算符的唯一说法是在15.26.2 Compound Assignment Operators:
A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.
这似乎不起作用(见上文)。
所以我的问题是 - javac 和 JLS 之间究竟是什么关系,这个特定示例是 javac 中的错误还是 JLS 中的错误?