Tag: jls

在Java中,是一个可赋值给声明的变量iff的表达式。 它可以作为使用相同类型声明的参数传递吗?

这个问题的灵感来自Java 8:是否可以为变量分配方法引用? 。 正如我目前所理解的那样(可能不完全正确),调用fooMethod(FooType ft)作为fooMethod(myFooInstance)会导致fooMethod(myFooInstance)隐式赋值给myFooInstance的局部变量,其名称为ft ,并且其类型声明为FooType 。 显然,在这种情况下,我还可以将myFooInstance分配给类型为FooType的字段或局部变量,例如,在具有声明字段private FooType fooField ,使用this.fooField = myFooInstance; 。 但是,扫描JLS 8.4.1时,在处理方法参数时没有提及赋值。 类似地,JLS 5.3没有提到可分配性,至少对该部分的初始读数是这样。 那么,变量类型的规则是在严格调用和赋值上下文中使用相同的吗? (或者, 当且仅当它可以赋值给具有相同声明的字段/局部变量时,它是否可赋值给方法参数?) (相同的声明意味着字段/本地/参数不是最终的,并且出于此问题的目的不考虑字段的可见性/可访问性) 编辑: FooType不一定是具体的类,而是一个表达我的问题的工具。 它可以是function接口,普通旧接口,代理类,原语等。 要清楚地改写一下,是否有一个值(或函数调用/语言结构返回值的返回值),可以分配给: FooType ft; 或传递给 myMethod(FooType ft){ … 但对于FooType的某种类型选择(这将作为反例并使答案为“否”) 并非两者兼而有之 。

如何完全限定其包名与本地成员名冲突的类?

好的,这里是JLS专家的一个非常好奇的Java 7语言谜题。 以下代码不能用javac和Eclipse编译: package com.example; public class X { public static X com = new X(); public void x() { System.out.println(com.example.X.com); // cannot find symbol ^^^^^^^ } } 似乎成员com完全阻止从X访问com.*包。 但是,这并未得到彻底应用。 以下工作,例如: public void x() { System.out.println(com.example.X.class); } 我的问题: 这种行为如何从JLS中certificate是正确的? 我该如何解决这个问题 请注意,这只是对生成代码中的实际问题的简化,其中需要完全限定com.example.X并且无法重命名com成员。 更新 :我认为它实际上可能是类似这样的问题: 为什么我不能在Java中“静态导入”一个“等于”方法?

勘误表Java语言规范第3版

我广泛使用JLS作为学习和教学资源,但我注意到它有一些错误。 有简单的错别字(例如JLS 5.1.4 “convesions”),但也有一些我认为是非常严重的错误。 例如, JLS 18.1 Java编程语言的语法应该是Java语言语法的权威参考,但它包含一个永远不会被使用的生产规则! (例如MoreStatementExpressions )。 当然,这是给定语法其他部分中更严重错误的标志,对吧? 那么第三版是否有勘误表? 会有吗? 我们应该向Sun / Oracle发送错误吗? 会不会有第4版?

JVM在加载特定类时是否加载所有使用的类?

当JVM加载A类时,它是否加载A中使用的所有类? 而且我想知道导入声明是否对加载过程有某种影响? JLS的链接将不胜感激。

为什么接口根据类文件格式扩展Object?

为什么JVM规范声明接口必须具有java/lang/Object的super_class ,即使接口不扩展java/lang/Object ? 我特别指的是JVM规范的§4.1 ,它说: 对于接口,super_class项的值必须始终是constant_pool表的有效索引。 该索引处的constant_pool条目必须是表示Object类的CONSTANT_Class_info结构。 但是在JLS的第9.2节中,它说接口不扩展Object。 而是声明一个隐式创建的抽象方法,它匹配Object类中的每个公共方法: 如果接口没有直接的超接口,则接口隐式声明一个公共抽象成员方法m,其中包含签名s,返回类型r和throws子句t,对应于每个公共实例方法m,其中包含签名s,返回类型r和throws子句t在Object中声明,除非接口显式声明具有相同签名,相同返回类型和兼容throws子句的方法。

JLS的哪一部分表示匿名类不能拥有public / protected / private成员类

考虑这段代码: public class TopLevelClass { Cloneable c = new Cloneable() { private int privateField; private void privateMethod() {}; }; } 有一个匿名类,它有一个private成员字段和一个private成员方法。 它已成功编译。 然后考虑这个: public class TopLevelClass { Cloneable c = new Cloneable() { private class PrivateInnerClass {} }; } 有一个匿名类,它有一个private成员类。 然而… javac说: error: modifier private not allowed here Eclipse说: Illegal modifier for the local class […]

注释属性必须是类文字? 为什么? 常数也应该没问题

有人可以解释为什么String和Class注释参数的预期不同吗? 为什么编译器需要Classes的文字,wherby也接受字符串的常量? 使用Spring的@RequestMapping的工作示例: public class MyController { public static final String REQUEST_MAPPING = “/index.html”; @RequestMapping(MyController.REQUEST_MAPPING) // ALL OK! … } 使用TestNG的@Test的WTF示例: public class MyControllerTest { public static final Class TEST_EXCEPTION = RuntimeException.class; @Test(expectedExceptions = MyControllerTest.TEST_EXCEPTION) // compilation error, WTF: // The value for annotation attribute Test.expectedExceptions must be a class literal … } 什么工作当然是@Test(expectedExceptions = […]

双重检查锁定的无序写入

在针对双重检查锁定方案的无序写入中提到的示例中(参考: IBM文章和维基百科文章 ) 在构造函数完全初始化之前,我无法理解为什么Thread1会在同步块中出现的简单原因。 根据我的理解,创建“new”和调用构造函数应该按顺序执行,同步锁不应该释放,直到所有工作都没有完成。 请让我知道我在这里失踪了什么。

为什么带有varargs的Java方法被识别为瞬态?

我正在使用Java Reflection API,并观察到具有可变参数列表的方法变得短暂。 为什么这个以及transient关键字在这种情况下意味着什么? 来自Java词汇表, 瞬态 : Java编程语言中的关键字,指示字段不是对象的序列化forms的一部分。 当对象被序列化时,其瞬态字段的值不包括在串行表示中,而其非瞬态字段的值包括在内。 然而,这个定义没有说明方法。 有任何想法吗? import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class Dummy { public static void main(String[] args) { for(Method m : Dummy.class.getDeclaredMethods()){ System.out.println(m.getName() + ” –> “+Modifier.toString(m.getModifiers())); } } public static void foo(int… args){} } 输出: main –> public static foo –> public static transient

Java编译器如何为具有多个边界的参数化类型选择运行时类型?

我想更好地理解当Java编译器遇到如下方法的调用时会发生什么。 void printType(T… args) { System.out.println(args.getClass().getComponentType().getSimpleName()); } // printType() prints “AutoCloseable” 我很清楚,在运行时没有类型 ,所以编译器做了它可以做的最不对的事情,并创建一个类型为两个边界接口之一的数组,丢弃另一个。 无论如何,如果切换接口的顺序,结果仍然是相同的。 void printType(T… args) { System.out.println(args.getClass().getComponentType().getSimpleName()); } // printType() prints “AutoCloseable” 这导致我做了一些调查,看看接口发生变化时会发生什么。 在我看来,编译器使用某种严格的顺序规则来决定哪个接口是最重要的 ,并且接口在代码中出现的顺序不起作用。 // “AutoCloseable” // “AutoCloseable” // “Serializable” // “Serializable” // “SafeVarargs” // “SafeVarargs” // “Channel” // “Channel” // “Channel” 问题:当存在多个边界时,Java编译器如何确定参数化类型的varargs数组的组件类型? 我甚至不确定JLS是否对此有所说明,而且我通过谷歌搜索发现的任何信息都没有涵盖这一特定主题。