首页 文章

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

提问于
浏览
216

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

  • 这种技术是否有一个整洁的名称(类似于 innernestedanonymous )?

  • JLS说系统 may 强制执行这些辅助类不能 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;
}

7 回答

  • 21

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

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

  • 0

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

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

    Foo.java包含:

    • 公共课Foo

    Bar.java包含:

    • 公共类酒吧

    • class Baz

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

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

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

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

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

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

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

  • 4

    我相信你只是简单地称之为 PrivateImplnon-public top-level class . 您也可以声明 non-public top-level interfaces .

    例如,SO上的其他地方:Non-public top-level class vs static nested class

    至于版本之间的行为变化,有关于1.2.2中的"worked perfectly"的讨论 . 但在太阳的论坛中停止了1.4的工作:Java Compiler - unable to declare a non public top level classes in a file .

  • 113

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

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

    1.这个技术有一个整洁的名称(类似于内部,嵌套,匿名)?

    多级单文件演示 .

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

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

  • 1

    根据Effective Java第2版(第13项):

    “如果只有一个类使用了包私有顶级类(或接口),请考虑使顶级类成为使用它的唯一类的私有嵌套类(第22项) . 这会降低其可访问性它的包中的所有类都使用它的一个类 . 但是,减少无偿公共类的可访问性比包私有顶级类更重要:......“

    根据成员类是否需要访问封闭实例(第22项),嵌套类可以是静态的或非静态的 .

  • 120

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

    public class Foo {
    
        public static class FooChild extends Z {
            String foo;
        }
    
        public static class ZeeChild extends Z {
    
        }
    
    }
    

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

    public class Bar {
    
        public static void main(String[] args){
    
            Foo.FooChild f = new Foo.FooChild();
            System.out.println(f);
    
        }
    }
    

    把它们放在同一个文件夹中 . 编译:

    javac folder/*.java
    

    并运行:

    java -cp folder Bar
    

相关问题