[java] Java : 하나의 파일에 여러 클래스 선언

Java에서는 단일 파일에서 여러 최상위 레벨 클래스를 정의 할 수 있으며,이 중 최대 하나가 공개되어 있습니다 ( JLS §7.6 참조 ). 예를 들어 아래를 참조하십시오.

  1. 이 기술에 대한 단정 한 이름 (유사 있는가 inner, nested, anonymous)?

  2. JLS에 따르면 시스템 이러한 2 차 클래스가 referred to by code in other compilation units of the package패키지 개인 클래스 로 취급 될 수없는 이러한 2 차 클래스를 제한 할 수 있다고 제한합니다 . 실제로 Java 구현간에 변경되는 것이 있습니까?

예를 들어 PublicClass.java :

package com.example.multiple;

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

class PrivateImpl {
    int implementationData;
}



답변

이 기술의 제안 된 이름 (단일 소스 파일에 여러 최상위 클래스 포함)은 “mess”입니다. 진지하게, 나는 그것이 좋은 생각이라고 생각하지 않습니다-대신이 상황에서 중첩 유형을 사용합니다. 그러면 어떤 소스 파일이 들어 있는지 쉽게 예측할 수 있습니다.이 방법에 대한 공식 용어는 없다고 생각합니다.

이것이 실제로 구현간에 변경되는지 여부에 대해서는 의심 스럽지만 처음부터 수행하지 않으면 걱정할 필요가 없습니다. 🙂


답변

javac는 이것을 적극적으로 금지하지 않지만, 파일과 같은 이름을 갖지 않으면 다른 파일에서 최상위 클래스를 참조하고 싶지 않다는 한계가 있습니다.

Foo.java와 Bar.java라는 두 파일이 있다고 가정하십시오.

Foo.java는 다음을 포함합니다 :

  • 공공 클래스 푸

Bar.java는 다음을 포함합니다.

  • 공공 클래스 바
  • 학급

또한 모든 클래스가 동일한 패키지에 있고 파일이 같은 디렉토리에 있다고 가정 해 봅시다.

Foo.java가 Baz가 아닌 Barz를 참조하고 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를 남겨둔 경우)이 오류는 사라집니다. 그러나 이것은 빌드 프로세스를 매우 신뢰할 수없고 색다른 느낌으로 만듭니다.

실제 제한은 “파일과 이름이 같거나 이름이 같은 파일에있는 클래스를 참조하지 않는 한 다른 파일의 최상위 클래스를 참조하지 않습니다. 파일과 같은 것은 “따라하기가 쉽지 않습니다. 사람들은 일반적으로 각 파일에 하나의 최상위 클래스를 배치하는 훨씬 더 직접적인 (그러나 더 엄격한) 규칙을 따릅니다. 수업이 공개되어야하는지 아닌지에 대해 마음이 바뀌면 더 좋습니다.

때때로 모든 사람이 특정한 방식으로 무언가를하는 좋은 이유가 있습니다.


답변

나는 당신이 단순히 PrivateImpl그것을 무엇 이라고 부르는지 믿습니다 non-public top-level class. 선언 할 수도 non-public top-level interfaces있습니다.

예를 들어 SO의 다른 곳 : 비공개 최상위 클래스 대 정적 중첩 클래스

버전 간 동작 변경에 대해서는 1.2.2에서 “완벽하게 작동 한”항목에 ​​대한 논의가있었습니다. Java 포럼 에서 파일에서 비 공용 최상위 레벨 클래스를 선언 할 수 없습니다 .


답변

이 수업을 원하는만큼 가질 수 있습니다

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


답변

1.이 기술에 대한 확실한 이름이 있습니까 (내부, 내포, 익명과 유사)?

멀티 클래스 단일 파일 데모.

JLS는 시스템이 패키지의 다른 컴파일 단위에서 코드로 이러한 보조 클래스를 참조 할 수 없다는 제한을 적용 할 수 있다고 말합니다 (예 : 패키지 전용으로 처리 할 수 ​​없음). 실제로 Java 구현간에 변경되는 것이 있습니까?

나는 그 제한이없는 것을 알지 못합니다-모든 파일 기반 컴파일러는 클래스 이름과 동일하지 않은 파일의 소스 코드 클래스를 참조 할 수 없습니다. (멀티 클래스 파일을 컴파일하고 클래스 경로에 클래스를 넣으면 모든 컴파일러에서 찾을 수 있습니다)


답변

Effective Java 2nd edition (Item 13)에 따르면 :

“패키지 전용 최상위 클래스 (또는 인터페이스)가 하나의 클래스에서만 사용되는 경우 최상위 클래스를이를 사용하는 유일한 클래스의 전용 중첩 클래스로 만드는 것을 고려하십시오 (항목 22). 패키지에있는 클래스를 사용하는 클래스에 대한 클래스이지만 패키지 개인 최상위 클래스보다 무상 공개 클래스의 액세스 가능성을 줄이는 것이 훨씬 중요합니다. … “

중첩 클래스는 멤버 클래스가 엔 클로징 인스턴스에 액세스해야하는지 여부에 따라 정적 또는 비정적일 수 있습니다 (항목 22).


답변

예, 외부 정적 클래스의 공용 정적 멤버와 함께 다음과 같이 할 수 있습니다.

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