Java:一个文件中的多个类声明

在Java中,您可以在一个文件中定义多个顶级类,只要其中一个是公共的(参见JLS第7.6节 )。 看下面的例子。

  1. 这个技术是否有一个整洁的名字(类似于innernestedanonymous )?

  2. JLS表示,系统可能会强制限制这些二级类不能被referred to by code in other compilation units of the package ,例如,它们不能被视为包私有。 这是否真的是Java实现之间的变化?

例如,PublicClass.java:

 package com.example.multiple; public class PublicClass { PrivateImpl impl = new PrivateImpl(); } class PrivateImpl { int implementationData; } 

我为这种技术build议的名称(包括单个源文件中的多个顶级类)将是“混乱”。 说真的,我不认为这是一个好主意 – 我会在这种情况下使用嵌套types。 然后,很容易预测它的源文件。我不相信这个方法有一个正式的术语。

至于这是否实际上在实现之间改变 – 我非常怀疑,但如果你避免这样做,你永远不需要关心:)

javac并没有主动禁止这个function,但是它的确有一个限制,就是说,除非它和它所在的文件有相同的名字,否则你永远不会想从别的文件中引用一个顶级的类。

假设你有两个文件,Foo.java和Bar.java。

Foo.java包含:

  • 公共课Foo

Bar.java包含:

  • 公共课吧
  • class巴兹

我们还要说,所有的类都在同一个包中(并且这些文件在同一个目录中)。

如果Foo.java引用Baz而不是Bar并且我们试图编译Foo.java会发生什么? 编译失败,像这样的错误:

 Foo.java:2: cannot find symbol symbol : class Baz location: class Foo private Baz baz; ^ 1 error 

这是有道理的,如果你想一想。 如果Foo.java引用Baz,但没有Baz.java(或Baz.class),那么javac如何知道要查找的源文件?

如果您改为告诉javac同时编译Foo.java和Bar.java,或者即使您之前编译过Bar.java(离开Baz.class,javac可以find它),那么这个错误就会消失。 这使得你的构build过程感觉非常不可靠和片状。

因为实际的限制,更像是“不要引用另一个文件中的顶级类,除非它与它所在的文件具有相同的名称,或者您也指的是位于同一个文件中的类与文件一样的东西“是一种难以遵循的方式,人们通常会在每个文件中放置一个顶级类的时候,使用更为直接的(尽pipe更严格的)惯例。 如果你想改变一个class级是否应该公开,这也会更好。

有时候,每个人都以某种特定的方式来做某件事,真的有一个好的理由。

我相信你只是简单的称呼PrivateImpl是一个non-public top-level class 。 您也可以声明non-public top-level interfaces

例如,在SO的其他地方: 非公共顶级类与静态嵌套类

至于版本之间的行为变化,有关于1.2.2中“完美运行”的讨论。 但在sun的论坛中停止了1.4的工作: Java编译器 – 无法在文件中声明非公共顶级类 。

你可以像这样有许多类

 public class Fun { Fun() { System.out.println("Fun constructor"); } void fun() { System.out.println("Fun mathod"); } public static void main(String[] args) { Fun fu = new Fun(); fu.fun(); Fen fe = new Fen(); fe.fen(); Fin fi = new Fin(); fi.fin(); Fon fo = new Fon(); fo.fon(); Fan fa = new Fan(); fa.fan(); fa.run(); } } class Fen { Fen() { System.out.println("fen construuctor"); } void fen() { System.out.println("Fen method"); } } class Fin { void fin() { System.out.println("Fin method"); } } class Fon { void fon() { System.out.println("Fon method"); } } class Fan { void fan() { System.out.println("Fan method"); } public void run() { System.out.println("run"); } } 

这个技术有一个整洁的名字(类似于内部的,嵌套的,匿名的)?

多类单文件演示。

2.JLS表示,系统可以强制限制这些二级类不能被包的其他编译单元中的代码引用,例如它们不能被视为包私有。 这是否真的是Java实现之间的变化?

我不知道有没有这种限制 – 所有基于文件的编译器将不允许您引用源文件中的类名称不相同的文件中的源代码类。 (如果你编译一个多类文件,并把类放在类path上,那么任何编译器都会find它们)

根据Effective Java第2版(第13项):

“如果只有一个类使用了包 – 私有的顶级类(或接口),可以考虑使顶层类成为使用它的唯一类的私有嵌套类(第22项)。把它的包中的类放到使用它的一个类中,但是减less无用公共类的可访问性比一揽子私有的顶级类更加重要:…“

根据成员类是否需要访问封闭实例(第22项),嵌套类可以是静态的也可以是非静态的。