Java类文件可以使用保留关键字作为名称吗?
我知道Java是一种可编译的编程语言,与Java不同,Java是JVM执行的字节码格式。有一些在.class格式中有效但在.java源代码中无效的示例,例如无构造函数类和合成方法Java类文件可以使用保留关键字作为名称吗?,java,reflection,jvm,.class-file,Java,Reflection,Jvm,.class File,我知道Java是一种可编译的编程语言,与Java不同,Java是JVM执行的字节码格式。有一些在.class格式中有效但在.java源代码中无效的示例,例如无构造函数类和合成方法 如果我们手工制作一个带有保留Java语言关键字(例如,int,while)的.class文件作为类、方法或字段名,Java虚拟机会接受它进行加载吗 如果加载了该类,是否意味着访问该类或成员的唯一方法是通过Java反射,因为该名称在Java编程语言中在语法上是非法的 关键字只有编译器知道。编译器翻译 将它们转换为足够的字
int
,while
)的.class文件作为类、方法或字段名,Java虚拟机会接受它进行加载吗是的,你可以使用保留字。这些词只适用于编译器。它们不会出现在生成的字节码中 使用保留Java字的一个例子是在基于JVM的Scala语言中。Scala的结构和语法与Java不同,但编译成Java字节码,以便在JVM上运行 这是合法的Scala:
class `class`
这定义了一个名为class
且无参数构造函数的类。在编译的class.class
文件上运行javap
(反汇编程序)显示
public class class {
public class();
}
Scala可以对任何其他Java保留字执行相同的操作
class int
class `while`
class goto
它们也可以用于方法或字段名
正如您所怀疑的,除了反射之外,您将无法从Java使用这些类。您可以从类似的“定制”类文件中使用它们,例如,从Scala编译器生成的类文件中
总之,这是javac(编译器)的限制,而不是java(VM/运行时环境)。字节码级别对类名的唯一限制是它们不能包含字符
[
、
或;
并且它们的长度最多为65535字节。这意味着您可以自由使用保留字、空格、特殊字符、Unicode,甚至是新行等奇怪的东西
理论上,您甚至可以在类名中使用空字符,但由于文件名中不可能有空字符,因此您不能将此类类文件包含在jar中。不过,您可以动态创建和加载一个类文件
以下是您可以做的一些事情的示例(用Krakatau汇编编写):
执行输出:
Hello from int
Hello from -42
Hello from
Hello from some whitespace and tabs
Hello from new
line
Hello from name with "Quotes" in it
有关JVM规范中规则的确切引用,请参阅。JVM规范中固定了有关名称的限制: 出现在类文件结构中的类和接口名称始终以称为二进制名称(JLS§13.1)的完全限定形式表示。此类名称始终表示为
CONSTANT\u Utf8\u info
结构(§4.4.7),因此可以从整个Unicode代码空间中绘制(不受进一步限制)
由于历史原因,类文件结构中出现的二进制名称的语法与JLS§13.1中记录的二进制名称的语法不同。在这种内部形式中,通常分隔构成二进制名称的标识符的ASCII句点(
)被ASCII正斜杠(/
)取代标识符本身必须是非限定名称(§4.2.2)。
方法、字段、局部变量和形式参数的名称存储为非限定名称。非限定名称必须至少包含一个Unicode代码点,并且不得包含任何ASCII字符;
[
/
(即句点或分号或左方括号或正斜杠)
方法名称进一步受到限制,因此,除特殊方法名称
和
(§2.9)外,它们不得包含ASCII字符
(即左尖括号或右尖括号)
因此,答案是,只有少数字符不能在二进制级别使用。首先,/
是包分隔符。然后,;
和[
不能使用,因为它们在和中具有特殊含义,可能包含类型名。在这些签名中,[
启动一个数组类型,并;
标记引用类型名称的结尾
没有明确的理由禁止使用
。它不在JVM中使用,只在中有意义,但如果您使用的是泛型签名,则类型名将进一步受到限制,不允许包含
,:
,并且这些字符在泛型签名中也有特殊意义
因此,在标识符中使用
违反规范对JVM的主要功能没有影响。有混淆器这样做。产生的代码可以工作,但在请求泛型类型签名时可能会遇到反射问题。此外,通过替换所有
s,则带有
s的/s将变得不可逆
可能有一点很有趣(参见第3点“外来标识符”),但它并没有进入最终的Java7。而且,似乎目前还没有人尝试引入它
还有一个附加的技术限制,即名称不能有更长的长度
Hello from int
Hello from -42
Hello from
Hello from some whitespace and tabs
Hello from new
line
Hello from name with "Quotes" in it