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

Mic*_*vis 230 java class

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

  1. 是否有此技术整洁名(类似于inner,nested,anonymous)?

  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;
}
Run Code Online (Sandbox Code Playgroud)

Lau*_*ves 125

javac没有主动禁止这一点,但它确实有一个限制,几乎意味着你永远不想从另一个文件引用顶级类,除非它与它所在的文件具有相同的名称.

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

Foo.java包含:

  • 公共课Foo

Bar.java包含:

  • 公共课吧
  • Baz级

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

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

Foo.java:2: cannot find symbol
symbol  : class Baz
location: class Foo
  private Baz baz;
          ^
1 error
Run Code Online (Sandbox Code Playgroud)

如果你考虑一下,这是有道理的.如果Foo.java引用了Baz,但是没有Baz.java(或Baz.class),javac怎么知道要查看哪个源文件?

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

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

有时,每个人都以某种特定的方式做某事真的有充分的理由.

  • "为什么它不起作用!"的优秀解释 (2认同)

Jon*_*eet 118

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

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

  • 我不是贬低者,但事实上这个答案可以被称为"规范"(即"你应该"而不是"事实上......但是......")是最可能的原因.我认为得到一个downvote.它实际上没有回答任何问题.就像提出一个无关的异常而不是返回任何东西/提出一个有关实际事实而不是意见的信息的例外. (66认同)
  • 我发现我认为@JonSkeet建议使用嵌套类型(我不同意)的一个小例外:如果主类是通用的,类型参数是第二类,则第二类不能嵌套.如果两个类紧密耦合(如问题中的PublicClass和PrivateImpl),我认为将PrivateImpl作为顶级类放在同一个文件中是个好主意. (6认同)
  • @BoomerRogers:不,这绝对不是"基于组件编程的核心基础".如果您针对组件进行编程,为什么还要关心源代码的组织方式?(我个人更喜欢依赖*注入*而不是服务定位器模式,但这是另一回事.)在你的脑海中分离API和源代码组织 - 它们是非常不同的东西. (6认同)
  • @JonSkeet 让我改写一下:您的“答案”是个人无关紧要的意见。(即“一团糟”和“我怀疑”之类的答案几乎没有价值。)因此,您的帖子没有回答提出的两个问题中的任何一个。检查 polygenelubricants 的答案,你会看到他设法回答了这两个问题。 (2认同)

pol*_*nts 22

我相信你只是称之为PrivateImpl:a non-public top-level class.你也可以申报non-public top-level interfaces.

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

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


Zhe*_*lov 10

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


小智 6

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

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 那没有回答问题。 (2认同)