如果存在内部类,则包含美元符号的 Java 类名将无法编译
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6167326/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java class name containing dollar sign fails to compile if an inner class is present
提问by Grzegorz Kossakowski
I've got following Java classes defined:
我定义了以下 Java 类:
mac-grek:javajunk grek$ cat A$B.java
class A$B {}
mac-grek:javajunk grek$ cat A.java
public class A {
public static class B {}
}
mac-grek:javajunk grek$ cat Main.java
public class Main {
public static void main(String[] args) {
System.out.println(A.B.class.getName());
System.out.println(A$B.class.getName());
}
}
When I try to compile them, I get following errors:
当我尝试编译它们时,出现以下错误:
mac-grek:javajunk grek$ javac 'A$B.java' A.java Main.java
A.java:2: duplicate class: A.B
public static class B {}
^
Main.java:4: cannot find symbol
symbol : class B
location: class A
System.out.println(A.B.class.getName());
^
Main.java:5: cannot find symbol
symbol : class A$B
location: class Main
System.out.println(A$B.class.getName());
^
3 errors
If I remove A.java
file and System.out.println(A.B.class.getName());
from Main.java
everything compiles:
如果我删除A.java
文件并System.out.println(A.B.class.getName());
从Main.java
所有内容中编译:
mac-grek:javajunk grek$ cat A$B.java
class A$B {}
mac-grek:javajunk grek$ cat Main.java
public class Main {
public static void main(String[] args) {
System.out.println(A$B.class.getName());
}
}
mac-grek:javajunk grek$ javac A$B.java Main.java
mac-grek:javajunk grek$
So Java allows me to define a class containing dollar sign in it's name. How can I compile my original example?
因此,Java 允许我定义一个名称中包含美元符号的类。如何编译我的原始示例?
回答by JB Nizet
You have a name conflict because you defined a top-level class A$B having the same name as the generated name for a static inner class B of class A. Since you have both, the compiler can't resolve the conflict.
您有名称冲突,因为您定义了一个顶级类 A$B,该类的名称与为类 A 的静态内部类 B 生成的名称相同。由于两者都有,编译器无法解决冲突。
The JLSsays:
JLS说:
The $ character should be used only in mechanically generated source code or, rarely, to access pre-existing names on legacy systems.
$ 字符应该只用在机械生成的源代码中,或者很少用于访问遗留系统上预先存在的名称。
Since you decided not to respect that rule, you got bitten by javac. I would just rename A$B to something else.
既然你决定不遵守这条规则,你就被 javac 咬了。我只是将 A$B 重命名为其他名称。
回答by Stephen C
This rule is very vague.
这个规则非常模糊。
I disagree. To me, it says "don't do it ... unless you know what you are doing". It doesn't say why, but it doesn't need to. Indeed, it can'tfully explain why because some of the uses of '$'
in identifiers could come from 3rd-party software.
我不同意。对我来说,它说“不要这样做......除非你知道自己在做什么”。它没有说为什么,但它不需要。实际上,它无法完全解释原因,因为'$'
in 标识符的某些用途可能来自 3rd 方软件。
Why javac would care if my code is coming from some generator or written by hand?
为什么 javac 会关心我的代码是来自某个生成器还是手工编写的?
It doesn't "care". But on the other hand it does assume that you know what you are doing if you choose to ignore the JLS advice.
它不“关心”。但另一方面,如果您选择忽略 JLS 建议,它确实假设您知道自己在做什么。
The point is that people who write generators are expected to know that the binary class names for inner classes are represented using the '$'
character. Other people should simply follow the advice in the JLS.
关键是编写生成器的人应该知道内部类的二进制类名是使用'$'
字符表示的。其他人应该简单地遵循 JLS 中的建议。
The reason that the Java Language Specification does not set out how the JVM uses '$'
is "separation of concerns". From the JLS perspective, this is just an implementation detail. Indeed, it is conceivable that someone will implement the Java language for a virtual machine platform that treats inner classes differently.
Java 语言规范没有规定 JVM 如何使用的原因'$'
是“关注点分离”。从 JLS 的角度来看,这只是一个实现细节。事实上,可以想象有人会为虚拟机平台实现 Java 语言,该平台以不同的方式对待内部类。
I'd like to know precisely in which cases I can use $ in names of my classes.
我想确切地知道在哪些情况下我可以在我的班级名称中使用 $ 。
It is not possible to answer that definitively. And it is probably a good thing that it is not possible; see below.
不可能肯定地回答这个问题。不可能是一件好事;见下文。
JLS should be very precise and formal and should not refer to reader's mental state when interpreting it's statements.
JLS 应该非常精确和正式,在解释它的陈述时不应该参考读者的心理状态。
There are some areas where it would be bad for the JLS to be formal and precise. This is one of them. For example, if they declared that '$' could safely if you followed rules X, Y and Z, this would limit theirpossible uses of '$' in future versions of Java. Changing the rules about what identifiers are workable could cause major source-code compatibility head-aches.
(Other areas where this principle applies are the Memory Model and the semantics of garbage collection.)
The JLS does not refer to your mental state. Those were mywords.
在某些领域,JLS 正式和精确是不利的。这是其中之一。例如,如果他们声明 '$' 可以安全地遵循规则 X、Y 和 Z,这将限制他们在未来版本的 Java 中可能使用 '$'。更改有关哪些标识符可用的规则可能会导致严重的源代码兼容性问题。
(此原则适用的其他领域是内存模型和垃圾收集的语义。)
JLS 不是指您的精神状态。那是我的话。
回答by Prince John Wesley
Both your class class A$B
and your static class B
shares the same. Compiler generates OuterClassName$InnerClassName
as class name for nested classes
你的班级class A$B
和你的static class B
共享是一样的。编译器生成OuterClassName$InnerClassName
嵌套类的类名