为什么你想要一个没有声明公共类的Java文件?

时间:2010-09-27 12:13:06

标签: java class

我正在阅读的书中有一篇关于SCJP资格的声明,它说:

  

没有公共类的文件没有   命名限制

这让我问,你为什么要这么做?

如果没有公共类,那么其他类如何导入和使用该文件呢?我能看到的唯一目的是文件本身是独立运行的,也可能是奇数,例如将整个应用程序放在一个文件中

5 个答案:

答案 0 :(得分:32)

这对package-private课程也有效。您可以在同一个包中使用package-private类。 (在这种情况下,你不必导入它,因为它在同一个包中。)

例如,JapaneseImperialCalendar类是package-private,因为它仅在Calendar.createCalendar(..)中使用 - 它不是公共API的一部分。您不能直接实例化日历,但您仍然可以通过其界面使用。对于通过Collections.unmodifiableList(..)等方法获得的所有不可修改的集合也是如此 - 它们是包私有的。

因此.java的{​​{1}}文件可能是任意的。但是,建议不要偏离在类名后命名甚至包私有文件的既定做法。

答案 1 :(得分:2)

您可以创建名为package-info.java的文件,该文件仅包含package语句。 javadoc 1.5+工具将此包语句上的javadoc注释视为package.html文件。此外,您可以在此语句中添加@Generated等程序包级注释,而package.html则无法执行此操作。

由于package-info不是有效的Java标识符,因此不存在此文件与现有Java类冲突的风险(即向后兼容性)。

答案 2 :(得分:1)

Java Classes开始,您有公共类和包类。包类被视为“私有”,因此您只能在包本身中使用它们。这是默认设置,即未指定 public

公共类当然是可以在任何地方创建的类。

答案 3 :(得分:-1)

即使我在回答这个问题时已经很晚了,但这肯定会有很大的帮助。如果我没有错,你的具体问题归结为这一点 - 一个声明没有没有显式修饰符的类的意义是什么?

查看 java.util 包中的此类 -

class JumboEnumSet<E extends Enum<E>> extends EnumSet<E>

同样在同一个包中看到 -

class RegularEnumSet<E extends Enum<E>> extends EnumSet<E>

您会看到它们都是使用无显式修饰符声明的。你有没有想过为什么包私有限制?以下是Joshua Bloch撰写的精彩书籍 Effective Java 2nd Edition#Item1

  

在发行版中引入的类 java.util.EnumSet(Item 32)   1.5,有   没有公共构造函数,只有静态工厂。它们返回两个实现中的一个,具体取决于底层枚举类型的大小:如果它有64个或更少的元素,   大多数枚举类型都是这样,静态工厂返回一个RegularEnumSet   实例,由a支持   单长;如果枚举类型有六十五个或更多元素,则工厂返回一个JumboEnumSet实例,由long支持   阵列。

快速移动,他进一步补充道 -

  

这两个实现类的存在是不可见的   客户端。如果RegularEnumSet不再提供性能优势   小枚举类型,它可以从未来的版本中删除,没有   不良影响。同样,未来版本可能会增加第三或第四   如果它被证明对性能有益,则实现EnumSet。   客户既不知道也不关心他们获得的对象的类   从工厂回来;他们只关心它是它的一些子类   EnumSet。

答案 4 :(得分:-2)

我不同意非限制。每个java文件应该只包含一个顶级类,文件名应该与类名相同,不管是public还是not。我不认为javac会非常喜欢这个(或任何人类)

A.java
    class B

B.java
    class A

http://java.sun.com/docs/books/jls/third_edition/html/packages.html#7.3

  

7.2软件包的主机支持

     

每个主机确定包的方式,   编译单元和子包是   创建和存储,以及   编译单元是可观察的   (§7.3)特定汇编。

     

7.2.1在文件系统中存储软件包

     

作为一个非常简单的例子,


http://download.oracle.com/javase/6/docs/technotes/tools/windows/javac.html

  

源文件和类文件都必须具有   标识类的根名称。   例如,一个名为MyClass的类   将写在源文件中   调用MyClass.java编译成   一个叫做的字节码类文件   MyClass.class。