Tag: jls

Java – 使用相同的方法和不同的返回类型实现多个接口

请考虑以下代码: public interface A { public A another(); } public interface B { public B another(); } public interface AB extends A,B { public AB another(); } 这导致AB上的编译错误: B型和A型不兼容; 两者都定义了另一个(),但具有不相关的返回类型 我已经看到了这个问题 ,并在接受的答案中遵循不兼容的例子 – 即 public interface C { public void doSomething(); } public interface D { public boolean doSomething(); } public interface CD extends C,D […]

通过reflection改变最终变量,为什么静态和非静态最终变量之间存在差异

请参考以下代码。 当我运行代码时,我能够更改最终的非静态变量的值。 但是如果我尝试更改最终静态变量的值,那么它会抛出java.lang.IllegalAccessException 。 我的问题是为什么它不会在非静态最终变量的情况下抛出exception,反之亦然。 为什么不同? import java.lang.reflect.Field; import java.util.Random; public class FinalReflection { final static int stmark = computeRandom(); final int inmark = computeRandom(); public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { FinalReflection obj = new FinalReflection(); System.out.println(FinalReflection.stmark); System.out.println(obj.inmark); Field staticFinalField = FinalReflection.class.getDeclaredField(“stmark”); Field instanceFinalField = FinalReflection.class.getDeclaredField(“inmark”); staticFinalField.setAccessible(true); instanceFinalField.setAccessible(true); instanceFinalField.set(obj, 100); […]

Java:重载方法解析和varargs – 令人困惑的例子

正当我认为我理解JLS15.12应用于varargs时,这是这个例子: package com.example.test.reflect; public class MethodResolutionTest2 { public int compute(Object obj1, Object obj2) { return 42; } public int compute(String s, Object… objects) { return 43; } public static void main(String[] args) { MethodResolutionTest2 mrt2 = new MethodResolutionTest2(); System.out.println(mrt2.compute(“hi”, mrt2)); System.out.println(mrt2.compute(“hi”, new Object[]{mrt2})); System.out.println(mrt2.compute(“hi”, new Object[]{mrt2, mrt2, mrt2})); } } 打印出来的 42 43 43 我理解第一行: […]

“合格的”构造在java中意味着什么?

在有效Java中的项目“项目22:偏爱非静态的静态成员类”Josh Bloch说: 非静态成员类的每个实例都与其包含类的封闭实例隐式关联。 在非静态成员类的实例方法中,您可以使用限定的此构造调用封闭实例上的方法或获取对封闭实例的引用。 他认为合格的建筑是什么意思?

最终字段初始化顺序

下面是一些在尚未初始化的类上调用静态方法Af()的代码。 有人可以用JLS来解释这段代码的行为吗? class A { final static Object b = new B(); final static int S1 = 1; final static Integer S2 = 2; static void f() { System.out.println(S1); System.out.println(S2); } } class B { static { Af(); } } public class App { public static void main( String[] args ) { Af(); } } […]

Enum类型中wrt到构造函数的静态块的执行顺序

这来自Effective Java: // Implementing a fromString method on an enum type private static final Map stringToEnum = new HashMap(); static { // Initialize map from constant name to enum constant for (Operation op : values()) stringToEnum.put(op.toString(), op); } // Returns Operation for string, or null if string is invalid public static Operation fromString(String symbol) { […]

为什么Java常量除以零会产生编译时错误?

可能重复: 1/0是合法的Java表达式吗? 为什么这段代码会编译? class Compiles { public final static int A = 7/0; public final static int B = 10*3; public static void main(String[] args) {} } 如果我查看已编译的类文件,我可以看到B已经被评估为30,而A仍然是7/0。 据我所知,JSL是一个除以零的表达式,不是常数。 参考: JLS 15.28 我的上述陈述是由于这一行: 编译时常量表达式是表示基本类型值的表达式 因此,除以零不会被评估为原始值。 我真的不明白为什么编译器允许这个呢? 为了清楚起见,上面的代码使用“java.lang.ExceptionInInitializerError”崩溃了运行时 在我看来,编译器威胁任何最终的静态变量作为常量并评估它的编译时间。 这意味着编译器已经尝试评估A,但由于它是零除以它只是让它通过。 没有编译时错误。 但这看起来非常奇怪…编译器知道它是一个除以零并且它会崩溃运行时但是它不会标记编译错误! 任何人都可以向我解释原因吗?

Java转换:是编译器错误,还是语言规范错误,还是我错了?

我一直在阅读Java语言规范第3版,并且发现了我认为规范和javac编译器实现之间的差异。 Eclipse编译器中存在相同的差异。 第15.16节讨论了强制转换表达式。 如果参数类型无法通过强制转换转换为强制类型,那么它应该是一个编译时错误(第5.5节): 如果操作数的编译时类型永远不会根据强制转换规则(第5.5节)强制转换为强制转换运算符指定的类型,那么这是一个编译时错误。 否则,在运行时,通过将转换转换为强制转换运算符指定的类型来转换操作数值(如果需要)。 第5.5节讨论了转换。 它给出了允许的转换类型列表。 列表中特别缺少的是“取消装箱转换,然后加宽/缩小原始转换”。 然而 ,javac编译器(以及Eclipse编译器)似乎确实允许确切的转换序列。 例如: long l = (long) Integer.valueOf(45); ……编译得很好。 (有问题的强制转换是强制转换;参数的类型为java.lang.Integer ,因此转换需要取消装箱到int后跟扩展的原始转换)。 同样,根据JLS,不应该从byte为char ,因为(根据5.1.4 )需要扩展原始转换和缩小基元转换 – 但是,编译器也允许这种转换。 任何人都可以开导我吗? 编辑:自从问这个以来,我已经向Oracle提交了一份错误报告 。 他们的反应是,这是“JLS中的一个小故障”。

关于在对象的构造函数完成之前对对象的引用

你们每个人都知道JMM的这个特性,有时候对象的引用可以在这个对象的构造函数完成之前获得值。 在JLS7中,p。 17.5 最后的字段语义我们也可以阅读: final字段的用法模型很简单:在该对象的构造函数中设置对象的final字段; 并且在对象的构造函数完成之前,不要在另一个线程可以看到的地方写入对正在构造的对象的引用 。 如果遵循此操作,那么当另一个线程看到该对象时,该线程将始终看到该对象的final字段的正确构造版本。 (1) 在JLS之后,接下来的例子展示了如何不保证非最终字段的初始化(1例17.5-1.1) (2) : class FinalFieldExample { final int x; int y; static FinalFieldExample f; public FinalFieldExample() { x = 3; y = 4; } static void writer() { f = new FinalFieldExample(); } static void reader() { if (f != null) { int i = fx; […]

具有固定/可变arity(varargs)匹配的最具体方法

在Java语言规范的第15.12.2.5节中 ,它讨论了如何在具有固定arity的方法和可变arity方法(即varargs )的两种情况下选择最具体的方法。 我在JLS中找不到的是关于两个方法之间的决定,其中一个是固定的arity,另一个是变量arity 。 例如: public interface SomeApi { public String getSomething(String arg); // method 1 public String getSomething(String … args); // method 2 } 按照人们的预期编译就好( 由Yoni概述的原因如下 )。 这个调用代码也编译: SomeApi api = … Object o = api.getSomething(“Hello”); 如果你运行它,则调用method #1 (即非varargs方法)。 为什么这个调用代码不含糊? 为什么固定arity方法比变量arnt方法更具体? 有人能指出我对规范的相关部分吗?