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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2336692/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 06:17:46  来源:igfitidea点击:

Java: Multiple class declarations in one file

javaclass

提问by Michael Brewer-Davis

In Java, you can define multiple top level classes in a single file, providing that at most one of these is public (see JLS §7.6). See below for example.

在 Java 中,您可以在单个文件中定义多个顶级类,前提是其中最多一个是公共的(参见JLS §7.6)。例如,请参见下文。

  1. Is there a tidy name for this technique (analogous to inner, nested, anonymous)?

  2. The JLS says the system mayenforce the restriction that these secondary classes can't be referred to by code in other compilation units of the package, e.g., they can't be treated as package-private. Is that really something that changes between Java implementations?

  1. 这种技术是否有一个简洁的名称(类似于inner, nested, anonymous)?

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

e.g., PublicClass.java:

例如,PublicClass.java:

package com.example.multiple;

public class PublicClass {
    PrivateImpl impl = new PrivateImpl();
}

class PrivateImpl {
    int implementationData;
}

采纳答案by Jon Skeet

My suggested name for this technique (including multiple top-level classes in a single source file) would be "mess". Seriously, I don't think it's a good idea - I'd use a nested type in this situation instead. Then it's still easy to predict which source file it's in. I don't believe there's an official term for this approach though.

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

As for whether this actually changes between implementations - I highly doubt it, but if you avoid doing it in the first place, you'll never need to care :)

至于这是否真的在实现之间发生变化 - 我非常怀疑,但如果你首先避免这样做,你就永远不需要关心:)

回答by Laurence Gonsalves

javac doesn't actively prohibit this, but it does have a limitation that pretty much means that you'd never want to refer to a top-level class from another file unless it has the same name as the file it's in.

javac 并没有主动禁止这样做,但它确实有一个限制,这几乎意味着您永远不想从另一个文件中引用顶级类,除非它与它所在的文件同名。

Suppose you have two files, Foo.java and Bar.java.

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

Foo.java contains:

Foo.java 包含:

  • public class Foo
  • 公开课 Foo

Bar.java contains:

Bar.java 包含:

  • public class Bar
  • class Baz
  • 公共课吧
  • 巴兹班

Let's also say that all of the classes are in the same package (and the files are in the same directory).

假设所有的类都在同一个包中(并且文件在同一个目录中)。

What happens if Foo.java refers to Baz but not Bar and we try to compile Foo.java? The compilation fails with an error like this:

如果 Foo.java 引用 Baz 而不是 Bar 并且我们尝试编译 Foo.java 会发生什么?编译失败,出现如下错误:

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

This makes sense if you think about it. If Foo.java refers to Baz, but there is no Baz.java (or Baz.class), how can javac know what source file to look in?

如果你仔细想想,这是有道理的。如果 Foo.java 指的是 Baz,但没有 Baz.java(或 Baz.class),javac 怎么知道要查找哪个源文件?

If you instead tell javac to compile Foo.java and Bar.java at the same time, or even if you had previously compiled Bar.java (leaving the Baz.class where javac can find it) then this error goes away. This makes your build process feel very unreliable and flaky, however.

如果您改为告诉 javac 同时编译 Foo.java 和 Bar.java,或者即使您之前已经编译了 Bar.java(将 Baz.class 留在 javac 可以找到它的地方),那么这个错误就会消失。然而,这会让你的构建过程感觉非常不可靠和不稳定。

Because the actual limitation, which is more like "don't refer to a top-level class from another file unless it has the same name as the file it's in or you're also referring to a class that's in that same file that's named the same thing as the 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.

因为实际的限制,更像是“不要从另一个文件引用顶级类,除非它与它所在的文件同名,或者你也指的是同一个文件中的类与文件相同的东西”有点难以理解,人们通常采用更直接(虽然更严格)的约定,即在每个文件中放置一个顶级类。如果您改变主意是否应该公开课程,这也会更好。

Sometimes there really is a good reason why everybody does something in a particular way.

有时,每个人都以特定方式做某事确实有充分的理由。

回答by polygenelubricants

I believe you simply call PrivateImplwhat it is: a non-public top-level class. You can also declare non-public top-level interfacesas well.

我相信您只是简单地称其PrivateImpl为: a non-public top-level class。您也可以声明non-public top-level interfaces

e.g., elsewhere on SO: Non-public top-level classvs static nested class

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

As for changes in behavior between versions, there was this discussion about something that "worked perfectly" in 1.2.2. but stopped working in 1.4 in sun's forum: Java Compiler - unable to declare a non public top level classes in a file.

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

回答by Pete Kirkham

1.Is there a tidy name for this technique (analogous to inner, nested, anonymous)?

1.这种技术有一个整洁的名字吗(类似于内部、嵌套、匿名)?

Multi-class single-file demo.

多类单文件演示。

2.The JLS says the system may enforce the restriction that these secondary classes can't be referred to by code in other compilation units of the package, e.g., they can't be treated as package-private. Is that really something that changes between Java implementations?

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

I'm not aware of any which don't have that restriction - all the file based compilers won't allow you to refer to source code classes in files which are not named the same as the class name. ( if you compile a multi-class file, and put the classes on the class path, then any compiler will find them )

我不知道有哪些没有这种限制——所有基于文件的编译器都不允许您在文件中引用与类名不同的源代码类。(如果你编译一个多类文件,并将类放在类路径上,那么任何编译器都会找到它们)

回答by Denis

You can have as many classes as you wish like this

您可以像这样拥有任意数量的课程

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");
    }
}

回答by rezzy

According to Effective Java 2nd edition (Item 13):

根据 Effective Java 2nd edition(Item 13):

"If a package-private top-level class (or interface) is used by only one class, consider making the top-level class a private nested class of the sole class that uses it (Item 22). This reduces its accessibility from all the classes in its package to the one class that uses it. But it is far more important to reduce the accessibility of a gratuitously public class than a package-private top-level class: ... "

“如果一个包私有的顶层类(或接口)只被一个类使用,考虑使顶层类成为使用它的唯一类的私有嵌套类(第 22 条)。这降低了它的可访问性将其包中的类分配给使用它的一个类。但减少无偿公共类的可访问性比包私有顶级类重要得多:......“

The nested class may be static or non-static based on whether the member class needs access to the enclosing instance (Item 22).

嵌套类可以是静态的或非静态的,这取决于成员类是否需要访问封闭实例(第 22 条)。

回答by Alexander Mills

Yes you can, with public static members on an outer public class, like so:

是的,您可以,在外部公共类上使用公共静态成员,如下所示:

public class Foo {

    public static class FooChild extends Z {
        String foo;
    }

    public static class ZeeChild extends Z {

    }

}

and another file that references the above:

和另一个引用上述内容的文件:

public class Bar {

    public static void main(String[] args){

        Foo.FooChild f = new Foo.FooChild();
        System.out.println(f);

    }
}

put them in the same folder. Compile with:

将它们放在同一个文件夹中。编译:

javac folder/*.java

and run with:

并运行:

 java -cp folder Bar

回答by Michal ?tein

No. You can't. But it is very possible in Scala:

不,你不能。但在 Scala 中很有可能:

class Foo {val bar = "a"}
class Bar {val foo = "b"}

回答by ZhekaKozlov

Just FYI, if you are using Java 11+, there is an exception to this rule: if you run your java file directly (without compilation). In this mode, there is no restriction on a single public class per file. However, the class with the mainmethod must be the first one in the file.

仅供参考,如果您使用的是 Java 11+,则此规则有一个例外:如果您直接运行 Java 文件(无需编译)。在这种模式下,对每个文件的单个公共类没有限制。但是,具有该main方法的类必须是文件中的第一个。