简体   繁体   English

为什么 Java 文件中只有 1 个公共 class

[英]Why only 1 public class in Java file

In any Java file, why can we have only one public class whose name is same as the Java file name?在任何 Java 文件中,为什么我们只能有一个与 Java 文件名相同的公共 class 文件?

It forces all Java code to be organized in a certain way , which in the long run helps improve code readability .它强制所有 Java 代码以某种方式组织,从长远来看,这有助于提高代码的可读性

The Java designers chose a strict approach that enforces their idea of good design practices, and this is part of that theme. Java 设计人员选择了一种严格的方法来执行他们的良好设计实践理念,这也是该主题的一部分。 Contrast that with the anything-goes attitude in Perl.将其与 Perl 中随心所欲的态度形成鲜明对比。

According to this source , it is for efficient compilation :根据这个来源,它是为了高效编译:

In the sidebar it explains why: "This restriction is not yet enforced by the compiler, although it's necessary for efficient package importation"在侧边栏中,它解释了原因:“编译器尚未强制执行此限制,尽管它是有效导入包所必需的”

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 文件)来确定哪些类在哪里,这会使编译变得更慢.

The same applies also for imports of source files in IDEs.这同样适用于 IDE 中源文件的导入。 Another reason would be reasonable source sizes.另一个原因是合理的源大小。

These are the rules.这些是规则。 Although it is not quite true.虽然这并不完全正确。 You can define internal classes inside you "main" class like this:您可以像这样在“主”类中定义内部类:

public class A {  
   public class B {  
       ...  
   }  
}

We can have only one top level public either class or interface in any java compilation unit ( .java source file ).在任何 java 编译单元(.java 源文件)中,我们只能有一个顶级公共类或接口。

But there can be any number of default classes/interfaces per src file.但是每个 src 文件可以有任意数量的默认类/接口。

why:为什么:

JLS leaves the option to the java compiler. JLS 将选项留给 java 编译器。 And most of the compiler implementations force to have file name same as :并且大多数编译器实现强制文件名与以下内容相同:

(1) the public class/interface name (1) 公共类/接口名

(2) if there is a main method and no public class then any name (2) 如果有一个 main 方法并且没有公共类,那么任何名称

(3) If there is main method and public class then main method should be in that public class (3)如果有主方法和公共类,那么主方法应该在那个公共类中

(4) if there is no public class and no main method then any valid name which may or may not be matching with the class/interface names in the file. (4) 如果没有公共类和主方法,则任何有效名称可能与文件中的类/接口名称匹配或不匹配。

From (2): If two public classes allowed, we should give the file two names which is terribly meaningless to file system.来自(2):如果允许两个公共类,我们应该给文件两个名字,这对文件系统来说是非常没有意义的。 From (3): If two public classes allowed, we should have two main methods which is terribly meaningless to java来自(3):如果允许两个公共类,我们应该有两个对java来说非常没有意义的主要方法

Hence a Java source file can have one only public class.因此,Java 源文件只能有一个公共类。

I think the above 4 points are forced by compiler to make the job of both compiler and jvm to find particular java source file or class file easy-so-quick for the compilation/loading/linking.我认为以上 4 点是编译器强制编译器和 jvm 为编译/加载/链接找到特定的 java 源文件或类文件的工作。 Java has such built in restrictions which developers should follow to have better programming. Java 有这样的内置限制,开发人员应该遵循这些限制以获得更好的编程。

Source: My readings and understanding.资料来源:我的阅读和理解。

To understand the basic reason behind these restrictions, let's suppose compiler doesn't give compile error for not naming file name same as public class name.为了理解这些限制背后的基本原因,让我们假设编译器没有因为文件名与公共类名不同而产生编译错误。

Suppose there is a package A假设有一个包 A

        A
      /   \
file1.java   file2.java

file1.java文件1.java

package A;

class file1
{
  public static void main(String args[])
  {

  }
}

public class file3
{
 public static void main(String args[])
 {

 }
}

Now as we know that a public class can also be accessed outside the package, now it will become the responsibility of a developer to make it accessible to the outside world.现在我们知道,公共类也可以在包外访问,现在开发人员有责任让外部世界访问它。 Let's see how:让我们看看如何:

Suppose package A is containing only Java files(no class files) and some class outside the package A tries to access public class file3, compiler will first try to find file3.class ( not available ), then it will try to find file3.java ( not available ).假设包 A 只包含 Java 文件(没有类文件)并且包 A 之外的某个类尝试访问公共类 file3,编译器将首先尝试查找 file3.class(不可用),然后它会尝试查找 file3.java ( 无法使用 )。 So even though file3 class is public in nature, it is not visible to the outside world.因此,即使 file3 类本质上是公共的,它对外界也是不可见的。 So if a compiler puts the restriction that if a file is containing public class, it should be named same as the public class name, then above issue can be resolved and the developer won't have to think of exposing public class to the outside world.因此,如果编译器限制如果文件包含公共类,则应将其命名为与公共类名相同,则可以解决上述问题,开发人员不必考虑将公共类暴露给外界.

Compiler also puts the restriction that there should be atmost one public class per Java file, so that every public class can be accessed by the outside world.编译器还限制每个Java文件最多只能有一个公共类,这样每个公共类都可以被外界访问。

Courtesy of Dr Heinz Kabutz and his excellent newsletter ....感谢 Heinz Kabutz 博士和他出色的时事通讯......

Why is each public class in a separate file?为什么每个公共类都在一个单独的文件中?

This is a question that I have frequently been asked during my courses.这是我在课程中经常被问到的一个问题。 Up to now I have not had a good answer to this question.到目前为止,我还没有很好地回答这个问题。 In section 1, we read: "Although each Oak compilation unit can contain multiple classes or interfaces, at most one class or interface per compilation unit can be public".在第 1 节中,我们读到:“虽然每个 Oak 编译单元可以包含多个类或接口,但每个编译单元最多可以有一个类或接口是公共的”。

In the sidebar it explains why: "This restriction is not yet enforced by the compiler, although it's necessary for efficient package importation"在侧边栏中,它解释了原因:“编译器尚未强制执行此限制,尽管它是有效导入包所必需的”

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 文件)来确定哪些类在哪里,这会使编译变得更慢.

Java utilizes this convention to find class/interface bytecode by starting at the classpath and scanning for the package hierarchy in subdirectories. Java 利用此约定通过从类路径开始并扫描子目录中的包层次结构来查找类/接口字节码。 Filesystem representation of this hierarchy also enforces some basic rules.此层次结构的文件系统表示还强制执行一些基本规则。

  1. Any two Java classes or interfaces in the same package cannot have the same name.同一包中的任何两个 Java 类或接口不能具有相同的名称。 File names would conflict.文件名会冲突。
  2. Any two Java packages in the same parent package could not have the same name.同一个父包中的任何两个 Java 包不能具有相同的名称。 Folder paths would conflict.文件夹路径会发生冲突。
  3. A class has visibility to all classes in the same package without modification to the classpath.一个类对同一个包中的所有类具有可见性,而无需修改类路径。

在编译器和程序员之间有一个理解。规则是源代码必须最多有一个公共类,并且该类必须包含主函数。因此,编译器可以在没有任何混淆/限制的情况下访问(公共)该类和将类名命名为类文件。此外,由于该类包含 main(),因此执行类文件将给出正确的流程

It enables a more efficient lookup of source ( .java) and compiled ( .class) files during compilation (import directive) and a more efficient classloading during execution.它可以在编译(导入指令)期间更有效地查找源文件( .java)和编译( .class)文件,并在执行期间更有效地加载类。 The idea being: if you know the name of a class, you know where it should be found for each classpath entry.这个想法是:如果你知道一个类的名字,你就知道每个类路径条目应该在哪里找到它。 No indexing required.不需要索引。

I think that this may be a possible reason.我认为这可能是一个可能的原因。 There can be only one public class in a java file because the name of java file is same as the name of public class.And obviously we can't have a file with two different names. java文件中只能有一个公共类,因为java文件的名称与公共类的名称相同。显然我们不能有两个不同名称的文件。

It is how it has been designed and I am not sure if the reason is documented.这就是它的设计方式,我不确定原因是否已记录在案。 But here is a good reason on why it is done that way.但这里有一个很好的理由说明为什么要这样做。 Let's assume we have two public classes Y & Z in a file named Y.java.假设我们在一个名为 Y.java 的文件中有两个公共类 Y 和 Z。 Now, let's assume a different class X is using Z. Now, when we compile X, the compiler first tries to locate Z.class and if it cannot find it, then it tries to locate Z.java so that it can compile it automatically.现在,假设另一个类 X 正在使用 Z。现在,当我们编译 X 时,编译器首先尝试定位 Z.class,如果找不到,则尝试定位 Z.java,以便它可以自动编译它. But, since we only have Y.java, the class Z cannot be located and hence we get a compilation error.但是,因为我们只有 Y.java,所以无法找到类 Z,因此我们得到一个编译错误。 So, we do need to place them in separate files.因此,我们确实需要将它们放在单独的文件中。

Public modifier with a class is exposed to the world that means any other class which is outside of the package can also access it to resolve dependency.带有类的公共修饰符向世界公开,这意味着包之外的任何其他类也可以访问它以解决依赖关系。 Now this dependency chain containing multiple classes are verified two times - one is while compilation ( one level of dependency is verified) & other one is while execution ( whole dependency chain is verified ).现在,这个包含多个类的依赖链被验证了两次——一次是编译时(验证了一级依赖),另一次是执行时(验证了整个依赖链)。

Now suppose there is public class (class A) whose source file name is something different from class name.现在假设有一个公共类(A 类),其源文件名与类名不同。 Now if some other class (say class B) depends on it , then while compilation of class B , java compiler will surely check where that class A is located & for that compiler has to go thru all the packages in search of class A ,which is time consuming.现在,如果其他一些类(比如 B 类)依赖于它,那么在编译 B 类时,java 编译器肯定会检查 A 类的位置,因为该编译器必须通过所有包来搜索 A 类,这很费时间。

Now suppose in the same scenario we give source file name of class A as A.java , then while compiling class B , compiler will search for class A & for that it only need to find source file whose name is A.java , so it doesn't need to go thru all packages ( which may contain multiple classes) it will now only search that package in which a source file A.java is present.现在假设在相同的场景中我们将类 A 的源文件名指定为 A.java ,那么在编译类 B 时,编译器将搜索类 A 并且它只需要找到名称为 A.java 的源文件,所以它不需要遍历所有包(可能包含多个类),它现在只会搜索包含源文件 A.java 的包。

So from compilation time , performance point if view one source file should have one public class.因此,从编译时间、性能角度来看,如果查看一个源文件应该有一个公共类。

Class A{ A类{


} public Class B{ } 公共 B 类{


} So this is correct becoz A is not public and compiler will not confuse that which class compiler should execute.所以这是正确的,因为 A 不是公共的,编译器不会混淆应该执行哪个类编译器。

public Class A{公共A类{


} public Class B{ } 公共 B 类{


} }

So this is incorrect becoz here compiler get confused which class should execute becoz both are public.所以这是不正确的,因为这里编译器会混淆应该执行哪个类,因为两者都是公共的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM