问题标签 [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.

0 投票
2 回答
971 浏览

java - Java 铸造:是编译器错了,还是语言规范错了,还是我错了?

我一直在阅读 Java 语言规范,第 3 版,并发现我认为规范和 javac 编译器实现之间存在差异。Eclipse 编译器中也存在相同的差异。

15.16节讨论了强制转换表达式。它说如果参数类型无法通过强制转换转换为强制类型转换(第 5.5 节),则应该是编译时错误:

如果操作数的编译时类型可能永远不会根据强制转换规则(第 5.5 节)强制转换为强制转换运算符指定的类型,则这是一个编译时错误。否则,在运行时,操作数的值会通过强制转换为强制转换运算符指定的类型进行转换(如有必要)。

5.5节讨论了强制转换。它给出了允许的转换类型列表。列表中特别缺少的是“拆箱转换,然后是扩大/缩小原始转换”。然而,javac 编译器(以及 Eclipse 编译器)似乎确实允许这种确切的转换顺序。例如:

...编译得很好。(有问题的转换是转换为long; 参数是 type java.lang.Integer,因此转换需要取消装箱,int然后是扩大的原始转换)。

同样,根据 JLS,应该不可能转换 from byteto char,因为(根据5.1.4)需要扩大原始转换缩小原始转换 - 但是,编译器也允许这种转换。

任何人都可以启发我吗?

编辑:因为问这个,我已经向 Oracle 提交了一个错误报告。他们的回应是,这是“JLS 中的一个小故障”。

0 投票
3 回答
3083 浏览

java - Java 语言规范第 4 版何时可用?

既然 JDK 7 开发人员预览版已经发布,人们可能会认为是时候推出新的 JLS。毕竟,语言已经发生了变化,尽管很小。

我还没有找到任何东西。什么时候可以使用新的 JLS,从哪里可以获得它?

0 投票
3 回答
2354 浏览

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插件是:

亲切的问候,
暴君

0 投票
3 回答
1687 浏览

java - JVM 在加载特定类时会加载所有使用的类吗?

当 JVM 加载一个类 A 时,它会加载 A 中使用的所有类吗?
我想知道进口声明是否对加载过程很重要?

到 JLS 的链接将不胜感激。

0 投票
3 回答
832 浏览

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 的相关部分。

0 投票
2 回答
2177 浏览

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

0 投票
2 回答
232 浏览

java - Java:编译时解析和“最具体的方法”

如果您尝试在下面使用重载函数compute1()compute2()和 ,则会导致编译错误:compute5()

在阅读了 JLS 第 15.12 节之后,我想我明白了......在匹配重载方法的第 2 阶段(允许装箱/拆箱,没有可变参数)中,在确定“最具体的方法”时,JLS 说(实际上)最特定方法是其形式参数是其他适用方法的子类型的方法,并且原语和对象(例如intInteger)绝不是彼此的子类型。SoInteger是 的子类型Integer,并且int是 的子类型int,但是Integer和与int/r/t 子类型比较不兼容,因此compute1()/compute2()对都没有最具体的方法。

(而 incompute3()compute4()带有String参数的方法比带有参数的方法更具体Object,所以程序打印 6 和 8。)

我的推理正确吗?

0 投票
1 回答
1010 浏览

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]),所以这个参数在它的范围内。(但事实并非如此!)

遵循相同的推理,每个通配符都在其范围内,所以这里有些地方是不对的……但是这个推理到底哪里出错了?这些规则在正确应用时如何运作

0 投票
1 回答
53 浏览

java - 我应该如何阅读 JLS 中的语法说明?

来自Java 语言规范(第三版),第 3.10.5 节

/blockquote>

有人可以帮我理解这种语法模式吗?可能意味着什么?xx: " xxxopt"

0 投票
3 回答
207 浏览

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 中的错误?