java 为什么每个公共类都在一个单独的文件中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1318712/
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
Why is each public class in a separate file?
提问by Sandbox
I recently started learning Java and found it very strange that every Java class must be declared in a separate file. I am a C# programmer and C# doesn't enforce any such restriction.
我最近开始学习Java,发现每个Java类都必须在一个单独的文件中声明很奇怪。我是一名 C# 程序员,C# 不强制执行任何此类限制。
Why does Java do this? Were there any design consideration?
Java为什么要这样做?有什么设计考虑吗?
Edit (based on few answers):
编辑(基于几个答案):
Why is Java not removing this restriction now in the age of IDEs? This will not break any existing code (or will it?).
为什么 Java 现在在 IDE 时代没有取消这个限制?这不会破坏任何现有的代码(或者会不会?)。
采纳答案by Mark Rushakoff
According to the Java Language Specification, Third Edition:
根据Java 语言规范第三版:
This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a compiler for the Java programming language or an implementation of the Java virtual machine to find a named class within a package; for example, the source code for a public type wet.sprocket.Toad would be found in a file Toad.java in the directory wet/sprocket, and the corresponding object code would be found in the file Toad.class in the same directory.
这个限制意味着每个编译单元最多只能有一个这样的类型。这种限制使得 Java 编程语言的编译器或 Java 虚拟机的实现可以轻松地在包中查找命名类。例如,公共类型wet.sprocket.Toad 的源代码将在目录wet/sprocket 的Toad.java 文件中找到,相应的目标代码将在同一目录下的Toad.class 文件中找到。
Emphasis is mine.
重点是我的。
It seems like basically they wanted to translate the OS's directory separator into dots for namespaces, and vice versa.
似乎基本上他们想将操作系统的目录分隔符转换为命名空间的点,反之亦然。
So yes, it was a design consideration of some sort.
所以是的,这是某种设计考虑。
回答by leora
I have just taken a C# solution and did just this (remove any file that had multiple public classes in them) and broke them out to individual files and this has made life much easier.
我刚刚采用了一个 C# 解决方案,并做到了这一点(删除其中包含多个公共类的任何文件)并将它们分解为单个文件,这使生活变得更加轻松。
If you have multiple public classes in a file you have a few issues:
如果你在一个文件中有多个公共类,你会遇到一些问题:
What do you name the file? One of the public classes? Another name? People have enough issues around poor solution code organization and file naming conventions to have one extra issue.
Also, when you are browsing the file / project explorer its good that things aren't hidden. For example you see one file and drill down and there are 200 classes all mushed together. If you have one file one class, you can organize your tests better and get a feel for the structure and complexity of a solution.
你给这个文件起什么名字?公开课之一?另一个名字?人们对糟糕的解决方案代码组织和文件命名约定有足够多的问题来解决一个额外的问题。
此外,当您浏览文件/项目资源管理器时,事情不会被隐藏是一件好事。例如,您看到一个文件并向下钻取,有 200 个类都混在一起。如果您有一个文件一个类,您可以更好地组织您的测试并了解解决方案的结构和复杂性。
I think Java got this right.
我认为 Java 做对了。
回答by VonC
From Thinking in Java
来自Java 的思考
:
:
There can be only one public class per compilation unit (file).
The idea is that each compilation unit has a single public interface represented by that public class. It can have as many supporting “friendly” classes as you want. If you have more than one public class inside a compilation unit, the compiler will give you an error message.
每个编译单元(文件)只能有一个公共类。
这个想法是每个编译单元都有一个由该公共类表示的公共接口。它可以有任意多的支持“友好”类。如果一个编译单元中有多个公共类,编译器会给你一个错误信息。
From the specification (7.2.6)
When packages are stored in a file system (?7.2.1), the host system may chooseto enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
- The type is referred to by code in other compilation units of the package in which the type is declared.
- The type is declared public (and therefore is potentially accessible from code in other packages).
- This restriction implies that there must be at most one such type per compilation unit.
- This restriction makes it easy for a compiler for the Java programming language or an implementation of the Java virtual machine to find a named class within a package; for example, the source code for a public type wet.sprocket.Toad would be found in a file Toad.java in the directory wet/sprocket, and the corresponding object code would be found in the file Toad.class in the same directory.
当包存储在文件系统 (?7.2.1) 中时,主机系统可以选择强制限制,如果在由类型名称加如果以下任一情况为真,则为扩展名(例如 .java 或 .jav):
- 该类型由声明该类型的包的其他编译单元中的代码引用。
- 该类型被声明为 public(因此可以从其他包中的代码访问)。
- 这个限制意味着每个编译单元最多只能有一个这样的类型。
- 这种限制使得 Java 编程语言的编译器或 Java 虚拟机的实现可以轻松地在包中查找命名类。例如,公共类型wet.sprocket.Toad 的源代码将在目录wet/sprocket 的Toad.java 文件中找到,相应的目标代码将在同一目录下的Toad.class 文件中找到。
In short: it may be about finding classes without having to load everything on your classpath.
简而言之:这可能是关于查找类而不必在类路径上加载所有内容。
Edit: "may choose" seems like it leaves the possibility to notfollow that restriction, and the meaning of "may" is probable the one described in RFC 2119(i.e. "optional")
In practice though, this is enforced in so many platform and relied upon by so many tools and IDE that I do not see any "host system" choosing to notenforce that restriction.
编辑:“可以选择”似乎留下了不遵循该限制的可能性,并且“可以”的含义可能是RFC 2119 中描述的那个(即“可选”),
但实际上,这在很多平台上都被强制执行并被如此多的工具和 IDE 所依赖,我没有看到任何“主机系统”选择不强制执行该限制。
From "Once upon an Oak ..."
出自《从前的橡树……》
It's pretty obvious - like most things are once you know the design reasons - the compiler would have to make an additional pass through all the compilation units (.java files) to figure out what classes were where, and that would make the compilation even slower.
很明显 - 就像大多数事情一样,一旦你知道设计原因 -编译器必须额外通过所有编译单元(.java 文件)来找出哪些类在哪里,这会使编译更慢.
(Note:
(笔记:
the Oak Language Specification for Oak version 0.2(postcript document): Oakwas the original name of what is now commonly known as Java, and this manual is the oldest manual available for Oak (i.e. Java).
For more history on the origins of Java, please have a look at the Green Projectand Java(TM) Technology: An Early History
)
Oak 0.2 版的Oak 语言规范(后记文档):Oak是现在通常称为 Java 的原始名称,本手册是 Oak(即 Java)可用的最古老的手册。
有关 Java 起源的更多历史,请查看绿色项目和Java(TM) 技术:早期历史
)
回答by oxbow_lakes
It's just to avoid confusionin the sense that Java was created with simplicity in mind from the perspective of the developer. Your "primary" classes are your public classes and they are easy to find (by a human) if they are in a file with the same name and in a directory specified by the class's package.
这只是为了避免混淆,因为从开发人员的角度来看,Java 是在考虑简单性的情况下创建的。您的“主要”类是您的公共类,如果它们位于具有相同名称的文件中并且位于类的包指定的目录中,则它们很容易(被人类)找到。
You must recall that the Java language was developed in the mid-90s, in the days before IDEs made code navigation and searching a breeze.
您一定记得 Java 语言是在 90 年代中期开发的,那时IDE 还没有使代码导航和搜索变得轻而易举。
回答by Zed
If a class is only used by one other class, make it a private inner class. This way you have your multiple classes in a file.
如果一个类仅被另一个类使用,请将其设为私有内部类。这样您就可以在一个文件中拥有多个类。
If a class is used by multiple other classes, which of these classes would you put into the same file? All three? You would end up having all your classes in a single file...
如果一个类被多个其他类使用,您会将这些类中的哪些放入同一个文件中?三个都?您最终会将所有课程都放在一个文件中......
回答by Andy White
That's just how the language designers decided to do it. I think the main reason was to optimize the compiler pass-throughs - the compiler does not have to guess or parse through files to locate the public classes. I think it's actually a good thing, it makes the code files much easier to find, and forces you to stay away from putting too much into one file. I also like how Java forces you to put your code files in the same directory structure as the package - that makes it easy to locate any code file.
这就是语言设计者决定这样做的方式。我认为主要原因是优化编译器传递 - 编译器不必猜测或解析文件来定位公共类。我认为这实际上是一件好事,它使代码文件更容易找到,并迫使您避免将太多内容放入一个文件中。我也喜欢 Java 如何强制您将代码文件放在与包相同的目录结构中 - 这使得查找任何代码文件变得容易。
回答by Stephen C
It is technically legal to have multiple Java top level classes in one file. However this is considered to be bad practice, and many Java tools (including IDEs) do not work if you do this.
在一个文件中包含多个 Java 顶级类在技术上是合法的。然而,这被认为是不好的做法,如果您这样做,许多 Java 工具(包括 IDE)将无法工作。
The JLS says this:
JLS 是这样说的:
When packages are stored in a file system (§7.2.1), the host system may choose to enforce the restrictionthat it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
- The type is referred to by code in other compilation units of the package in which the type is declared.
- The type is declared public (and therefore is potentially accessible from code in other packages).
当包存储在文件系统(第7.2.1节),主系统可以选择强制限制,这是一个编译时错误,如果一个类型没有在下方的类型名称加组成的名称的文件中找到如果以下任一情况为真,则为扩展名(例如 .java 或 .jav):
- 该类型由声明该类型的包的其他编译单元中的代码引用。
- 该类型被声明为 public(因此可以从其他包中的代码访问)。
Note the use of mayin the JLS text. This says that a compiler may reject this as invalid, or it may not. That is not a good situation if you are trying to build your Java code to be portable at the source code level. Thus, even if multiple classes in one source file works on your development platform, it is bad practice to do this.
请注意在 JLS 文本中使用may。这表示编译器可能会拒绝此无效,也可能不会。如果您试图将 Java 代码构建为在源代码级别具有可移植性,那么这不是一个好情况。因此,即使一个源文件中的多个类在您的开发平台上工作,这样做也是一种不好的做法。
My understanding is that this "permission to reject" is a design decision that is intended in partto make it easier to implement Java on a wider range of platforms. If (conversely) the JLS required all compilers to support source files containing multiple classes, there would be conceptual issues implementing Java on a platform which wasn't file-system based.
我的理解是,这种“拒绝许可”是一种设计决策,其部分目的是为了更容易地在更广泛的平台上实现 Java。如果(相反)JLS 要求所有编译器支持包含多个类的源文件,那么在不基于文件系统的平台上实现 Java 就会出现概念问题。
In practice, seasoned Java developers don't miss being able to do this at all. Modularization and information hiding are better done using an appropriate combination of packages, class access modifiers and inner or nested classes.
在实践中,经验丰富的 Java 开发人员根本不会错过能够做到这一点。使用包、类访问修饰符和内部或嵌套类的适当组合可以更好地完成模块化和信息隐藏。
回答by Hamza Yerlikaya
Why is java not removing this restriction now in the age of IDEs? This will not break any existing code (or will it?).
为什么在 IDE 时代 java 现在没有取消这个限制?这不会破坏任何现有的代码(或者会不会?)。
Now all code is uniform. When you see a source file you know what to expect. it is same for every project. If java were to remove this convention you have to relearn code structure for every project you work on, where as now you learn it once and apply it everywhere. We should not be trusting IDE's for everything.
现在所有的代码都是统一的。当您看到源文件时,您就知道会发生什么。每个项目都是一样的。如果java要删除这个约定,你必须为你工作的每个项目重新学习代码结构,就像现在一样,你学习一次并应用到任何地方。我们不应该相信 IDE 的一切。
回答by Hamza Yerlikaya
Not really an answer to the question but a data point none the less.
不是真正的问题的答案,但仍然是一个数据点。
I grepped the headers of my personal C++ utilty library (you can get it yourself from here) and almost all of the header files that actually do declare classes (some just declare free functions) declare more than one class. I like to think of myself as a pretty good C++ designer (though the library is a bit of a bodge in places - I'm its only user), so I suggest that for C++ at least, multiple classes in the same file are normal and even good practice.
我搜索了我的个人 C++ 实用程序库的头文件(您可以从这里自己获取)并且几乎所有实际声明类的头文件(有些只是声明自由函数)声明了不止一个类。我喜欢把自己想象成一个很好的 C++ 设计师(虽然这个库在某些地方有点笨拙——我是它唯一的用户),所以我建议至少对于 C++,同一个文件中的多个类是正常的甚至是好的做法。
回答by Thorbj?rn Ravn Andersen
It allows for simpler heuristics for going from Foobar.class to Foobar.java.
它允许从 Foobar.class 到 Foobar.java 的更简单的启发式方法。
If Foobar could be in any Java file you have a mapping problem, which may eventually mean you have to do a full scan of all java files to locate the definition of the class.
如果 Foobar 可能在任何 Java 文件中,那么您就会遇到映射问题,这可能最终意味着您必须对所有 Java 文件进行全面扫描才能找到类的定义。
Personally I have found this to be one of the strange rules that combined result in that Java applications can grow very large and still be sturdy.
就我个人而言,我发现这是一种奇怪的规则,这些规则结合在一起导致 Java 应用程序可以变得非常大并且仍然坚固。

