Java类文件可以使用保留关键字作为名称吗?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (14)

我知道Java可编译编程语言与JVM执行的Java字节码格式不同。在.class格式中有一些有效的例子,但不在.java源代码中,例如无构造函数的类和合成方法。

  1. 如果我们使用保留的Java语言关键字(例如,int,while)作为类,方法或字段名称手工创建一个.class文件,Java虚拟机是否会接受它加载?intwhile
  2. 如果该类被加载,是否意味着访问此类或成员的唯一方法是通过Java反射,因为该名称在Java编程语言中在语法上是非法的?
提问于
用户回答回答于

对字节码级别的类名称的唯一限制是它们不能包含字符[.或者;它们最长不超过65535字节。除此之外,这意味着你可以自由使用保留字,空白字符,特殊字符,Unicode,甚至像换行符这样的奇怪东西。

理论上,甚至可以在类名中使用空字符,但由于文件名中不能包含空字符,因此不能将这样的类文件包含在jar中。你也许能够动态地创建和加载一个。

下面是你可以做的一些事情的例子(用Krakatau汇编):

; Entry point for the jar
.class Main
.super java/lang/Object

.method public static main : ([Ljava/lang/String;)V
    .limit stack 10
    .limit locals 10
    invokestatic int                                hello ()V
    invokestatic "-42"                              hello ()V
    invokestatic ""                                 hello ()V
    invokestatic "  some  whitespace and \t tabs"   hello ()V
    invokestatic "new\nline"                        hello ()V
    invokestatic 'name with "Quotes" in it'         hello ()V
    return
.end method
.end class


.class int
.super java/lang/Object
.method public static hello : ()V
    .limit stack 2
    .limit locals 0
    getstatic java/lang/System out Ljava/io/PrintStream;
    ldc "Hello from int"
    invokevirtual java/io/PrintStream println (Ljava/lang/Object;)V
    return
.end method
.end class

.class "-42"
.super java/lang/Object
.method public static hello : ()V
    .limit stack 2
    .limit locals 0
    getstatic java/lang/System out Ljava/io/PrintStream;
    ldc "Hello from -42"
    invokevirtual java/io/PrintStream println (Ljava/lang/Object;)V
    return
.end method
.end class

; Even the empty string can be a class name!
.class ""
.super java/lang/Object
.method public static hello : ()V
    .limit stack 2
    .limit locals 0
    getstatic java/lang/System out Ljava/io/PrintStream;
    ldc "Hello from "
    invokevirtual java/io/PrintStream println (Ljava/lang/Object;)V
    return
.end method
.end class

.class "  some  whitespace and \t tabs"
.super java/lang/Object
.method public static hello : ()V
    .limit stack 2
    .limit locals 0
    getstatic java/lang/System out Ljava/io/PrintStream;
    ldc "Hello from   some  whitespace and \t tabs"
    invokevirtual java/io/PrintStream println (Ljava/lang/Object;)V
    return
.end method
.end class

.class "new\nline"
.super java/lang/Object
.method public static hello : ()V
    .limit stack 2
    .limit locals 0
    getstatic java/lang/System out Ljava/io/PrintStream;
    ldc "Hello from new\nline"
    invokevirtual java/io/PrintStream println (Ljava/lang/Object;)V
    return
.end method
.end class

.class 'name with "Quotes" in it'
.super java/lang/Object
.method public static hello : ()V
    .limit stack 2
    .limit locals 0
    getstatic java/lang/System out Ljava/io/PrintStream;
    ldc "Hello from name with \"Quotes\" in it"
    invokevirtual java/io/PrintStream println (Ljava/lang/Object;)V
    return
.end method
.end class

执行输出:

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
用户回答回答于

是的,你可以使用保留字。这些词仅用于编译器。它们不会出现在生成的字节码中。

使用保留的Java字的一个例子是基于JVM的Scala语言。Scala具有与Java不同的构造和语法,但编译为Java字节代码,以便在JVM上运行。

这是合法的Scala:

class `class`

这定义了一个以class无参数构造函数命名的类。运行javap(反汇编)在编译的class.class文件上显示

public class class {
    public class();
}

Scala可以对任何其他Java保留字执行相同的操作。

class int
class `while`
class goto

它们也可以用于方法或字段名称。

如你所怀疑的,除了反射之外,你将无法使用Java中的这些类。您可以使用类似“自定义”类文件中的这些文件,例如从Scala编译器生成的类文件中。

总之,这是javac(编译器)的限制,而不是Java(VM /运行时环境)。

扫码关注云+社区