[java] 자바 : 서브 패키지 가시성?

나는 내 프로젝트에서 두 패키지를 가지고 odp.projodp.proj.test. 이 두 패키지의 클래스에만 표시하려는 특정 메소드가 있습니다. 어떻게해야합니까?

편집 : Java에 하위 패키지 개념이 없으면이 방법이 있습니까? 테스터 및 해당 패키지의 다른 멤버에게만 제공되는 특정 방법이 있습니다. 모든 것을 동일한 패키지에 넣어야합니까? 광범위한 반사를 사용하십니까?



답변

당신은 할 수 없습니다. Java에는 하위 패키지의 개념이 없으므로odp.projodp.proj.test완전히 분리 된 패키지입니다.


답변

패키지 이름은 여기에서 응용 프로그램이 단위 테스트 용임을 암시합니다. 일반적으로 사용되는 패턴은 테스트하려는 클래스와 단위 테스트 코드를 동일한 패키지 (경우에 따라 odp.proj)이지만 다른 소스 트리에 배치하는 것입니다. 따라서 클래스를 넣고 src/odp/proj테스트 코드를에 넣으십시오 test/odp/proj.

Java에는 “패키지”액세스 수정자가 있습니다.이 수정자는 지정되지 않은 경우 기본 액세스 수정 자입니다 (즉, 공개, 개인 또는 보호를 지정하지 않음). “패키지”액세스 수정자를 사용하면 클래스의 클래스 만 odp.proj메소드에 액세스 할 수 있습니다. 그러나 Java에서는 액세스 수정자가 모든 액세스가 가능하므로 액세스 규칙을 적용하는 데 의존 할 수 없음을 명심하십시오. 제한적 보안 관리자가없는 경우 액세스 수정자는 단지 암시 적입니다.


답변

이 사이에 특별한 관계 없다 odp.proj하고 odp.proj.test– 그들은 단지 분명히 관련라는 이름으로 일이.

odp.proj.test 패키지가 단순히 테스트를 제공하는 경우 동일한 패키지 이름 ( odp.proj)을 사용할 수 있습니다 . Eclipse 및 Netbeans와 같은 IDE는 패키지 이름은 동일하지만 JUnit 시맨틱 을 사용하여 별도의 폴더 ( src/main/java/odp/projsrc/test/java/odp/proj)를 작성합니다.

이 IDE는 메소드에 대한 테스트를 odp.proj생성하고 존재하지 않는 테스트 메소드에 대한 적절한 폴더를 작성합니다.


답변

IntelliJ 에서이 작업을 수행하면 소스 트리는 다음과 같습니다.

src         // source root
- odp
   - proj   // .java source here
- test      // test root
  - odp
     - proj // JUnit or TestNG source here


답변

편집 : Java에 하위 패키지 개념이 없으면이 방법이 있습니까? 테스터 및 해당 패키지의 다른 멤버에게만 제공되는 특정 방법이 있습니다.

아마도 그것들을 표시하지 않는 동기에 약간 의존하지만 유일한 이유는 테스트를위한 것 (또는 다른 내부적 인 것)으로 공용 인터페이스를 오염시키고 싶지 않다면 메소드를 별도의 공용 인터페이스를 사용하고 “숨겨진”메서드 소비자가 해당 인터페이스를 사용하도록합니다. 다른 사람들이 인터페이스를 사용하는 것을 막지는 않지만 당신이 그럴 이유가 없습니다.

단위 테스트의 경우, 로트를 다시 쓰지 않고 가능하다면 제안에 따라 동일한 패키지를 사용하십시오.


답변

다른 사람들이 설명했듯이 Java에는 “하위 패키지”와 같은 것이 없습니다. 모든 패키지가 격리되어 부모로부터 아무것도 상속받지 않습니다.

다른 패키지에서 보호 된 클래스 멤버에 액세스하는 쉬운 방법은 클래스를 확장하고 멤버를 재정의하는 것입니다.

예를 들어 ClassInA패키지 에서 액세스하려면 a.b:

package a;

public class ClassInA{
    private final String data;

    public ClassInA(String data){ this.data = data; }

    public String getData(){ return data; }

    protected byte[] getDataAsBytes(){ return data.getBytes(); }

    protected char[] getDataAsChars(){ return data.toCharArray(); }
}

해당 패키지에서 필요한 메소드를 대체하는 클래스를 작성하십시오 ClassInA.

package a.b;

import a.ClassInA;

public class ClassInAInB extends ClassInA{
    ClassInAInB(String data){ super(data); }

    @Override
    protected byte[] getDataAsBytes(){ return super.getDataAsBytes(); }
}

그러면 다른 패키지의 클래스 대신 재정의 클래스를 사용할 수 있습니다.

package a.b;

import java.util.Arrays;

import a.ClassInA;

public class Driver{
    public static void main(String[] args){
        ClassInA classInA = new ClassInA("string");
        System.out.println(classInA.getData());
        // Will fail: getDataAsBytes() has protected access in a.ClassInA
        System.out.println(Arrays.toString(classInA.getDataAsBytes()));

        ClassInAInB classInAInB = new ClassInAInB("string");
        System.out.println(classInAInB.getData());
        // Works: getDataAsBytes() is now accessible
        System.out.println(Arrays.toString(classInAInB.getDataAsBytes()));
    }
}

이것은 확장 된 클래스 (상속)에 보이는 보호 된 멤버에 대해서만 작동하며 동일한 패키지 내의 하위 / 확장 클래스에만 보이는 패키지 전용 멤버에는 적용되지 않습니다. 잘만되면 이것은 누군가를 돕는다!


답변

여기에있는 대부분의 답변에 따르면 Java에는 하위 패키지와 같은 것은 없지만 정확히 정확하지는 않습니다. 이 용어는 Java 6에 이르기까지 Java 언어 사양에 있었으며 아마도 더 뒤로 돌아 왔습니다 (이전 버전의 Java에 대해서는 자유롭게 액세스 할 수있는 JLS 버전이 아닌 것 같습니다). Java 6부터 JLS에서 하위 패키지 관련 언어가 크게 변경되지 않았습니다.

자바 13 JLS :

패키지의 멤버는 하위 패키지와 패키지의 모든 컴파일 단위에 선언 된 모든 최상위 클래스 유형 및 최상위 인터페이스 유형입니다.

예를 들어, Java SE Platform API에서 :

  • 이 패키지에는 java하위 패키지가 awt, applet, io, lang, net,와 util,하지만 컴파일 단위를.
  • 이 패키지 java.awt에는 image클래스 및 인터페이스 유형의 선언을 포함하는 여러 컴파일 단위뿐만 아니라 라는 하위 패키지 가 있습니다.

서브 패키지 개념은 패키지와 클래스 / 인터페이스 간의 이름 지정 제약 조건을 적용하는 것과 관련이 있습니다.

패키지에는 동일한 이름의 두 멤버가 포함되어 있지 않거나 컴파일 타임 오류가 발생할 수 있습니다.

여기 몇 가지 예가 있어요.

  • 패키지 java.awt에는 서브 패키지 가 있으므로 image, 클래스 또는 인터페이스 유형의 선언을 포함 할 수 없으며 포함하지도 않습니다 image.
  • 해당 패키지에 이름이 지정된 패키지 mouse와 멤버 유형 Button(이후이라고도 함 mouse.Button)이 있으면 정규화 된 이름 mouse.Button또는을 가진 패키지가있을 수 없습니다 mouse.Button.Click.
  • 경우 com.nighthacks.java.jag유형의 완전한 이름은 다음 누구의 정규화 된 이름 중 어떤 패키지가있을 수 없다 com.nighthacks.java.jag거나 com.nighthacks.java.jag.scrabble.

그러나이 이름 제한은 언어별로 하위 패키지에 제공 되는 유일한 의미입니다.

패키지의 계층 적 이름 지정 구조는 일반적인 방식으로 관련 패키지를 구성하는 데 편리하도록 만들어졌지만 해당 패키지에 선언 된 최상위 유형과 이름이 같은 하위 패키지를 갖는 패키지에 대한 금지 외에는 그다지 의미가 없습니다. .

예를 들어,라는 이름의 패키지 사이에 특별한 접근 관계가없는 oliver명명 된 다른 패키지 oliver.twist, 또는 명명 된 패키지 사이에 evelyn.wood하고 evelyn.waugh. 즉, 이름 oliver.twist이 지정된 패키지의 oliver코드는 다른 패키지의 코드보다 패키지 내에 선언 된 유형에 더 잘 액세스 할 수 없습니다 .


이러한 맥락에서 질문 자체에 답할 수 있습니다. 패키지와 해당 서브 패키지 또는 상위 패키지의 두 개의 서로 다른 서브 패키지 사이에는 명시 적으로 특별한 액세스 관계가 없으므로 요청 된 방식으로 두 개의 서로 다른 패키지에 메소드를 표시 할 수있는 방법이 없습니다. 이것은 문서화 된 의도적 인 디자인 결정입니다.

메소드를 공개하고 모든 패키지 ( odp.proj및 포함 odp.proj.test)가 지정된 메소드에 액세스 할 수 있거나 메소드를 패키지 전용 (기본 가시성)으로 만들 수 있으며 메소드에 직접 액세스해야하는 모든 코드를 입력해야합니다. 방법과 동일한 (하위) 패키지.

즉, Java의 매우 표준 사례는 테스트 코드를 소스 코드와 동일한 패키지에 배치하지만 파일 시스템의 다른 위치에 배치하는 것입니다. 예를 들어,에 메이븐 빌드 도구,이 협약은 이러한 소스 및 테스트 파일을 배치하는 것 src/main/java/odp/proj
src/test/java/odp/proj각각. 빌드 도구가이를 컴파일하면 두 파일 세트가 모두 odp.proj패키지에 포함되지만 src파일 만 프로덕션 아티팩트에 포함됩니다. 테스트 파일은 빌드시에만 프로덕션 파일을 확인하는 데 사용됩니다. 이 설정을 통해 테스트 코드는 테스트중인 코드의 패키지 개인 코드 또는 보호 된 코드가 동일한 패키지에 있으므로 자유롭게 액세스 할 수 있습니다.

테스트 / 제작 사례가 아닌 하위 패키지 또는 형제 패키지에서 코드 공유를 원하는 경우 일부 라이브러리에서 사용하는 한 가지 해결책은 공유 코드를 공개로 설정하는 것이지만 내부 라이브러리 용으로 작성되었다는 것을 문서화하는 것입니다 사용하십시오.