在Java中,你可以在一个文件中定义多个顶级类,只要其中最多有一个是公共的(参见JLS§7.6)。请看下面的例子。
这种技术是否有一个整齐的名称(类似于内部的、嵌套的、匿名的)?
JLS表示,系统可能会强制限制这些二级类不能被包的其他编译单元中的代码引用,例如,它们不能被视为包私有。这真的是Java实现之间的变化吗?
例如,PublicClass.java:
package com.example.multiple;
public class PublicClass {
PrivateImpl impl = new PrivateImpl();
}
class PrivateImpl {
int implementationData;
}
Javac并没有主动禁止这样做,但它确实有一个限制,这在很大程度上意味着您永远不想从另一个文件引用顶级类,除非它与所在文件具有相同的名称。
假设您有两个文件,Foo.java和Bar.java。
Foo.java包含:
公共类Foo
Bar.java包含:
公共类酒吧
类巴兹
我们还假设所有的类都在同一个包中(文件在同一个目录中)。
如果Foo指向Baz而不是Bar,我们试图编译Foo.java会发生什么?编译失败,出现如下错误:
Foo.java:2: cannot find symbol
symbol : class Baz
location: class Foo
private Baz baz;
^
1 error
仔细想想,这是有道理的。如果Foo引用Baz,但没有bazz .java(或bazz .class), javac如何知道要查找哪个源文件?
如果您告诉javac同时编译Foo.java和Bar.java,或者您之前编译过Bar.java(将bazz .class留在javac可以找到它的地方),或者即使Foo碰巧引用了Bar而不是Baz,那么这个错误就会消失。然而,这会使您的构建过程感觉非常不可靠和不可靠。
Because the actual limitation, which is more like "don't refer to a top-level class from another file unless it either has the same name as the file it's in or you're also referring to another class that's named the same thing as that file that's also in that file" is kind of hard to follow, people usually go with the much more straightforward (though stricter) convention of just putting one top-level class in each file. This is also better if you ever change your mind about whether a class should be public or not.
新版本的javac也可以在这种情况下使用-Xlint:all生成警告:
auxiliary class Baz in ./Bar.java should not be accessed from outside its own source file
有时候确实有一个很好的理由,为什么每个人都以一种特定的方式做某事。