IT박스

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

itboxs 2020. 6. 24. 07:50
반응형

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


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

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


당신은 할 수 없습니다. Java에는 서브 패키지 개념이 없으므로 odp.proj와 odp.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()));
    }
}

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


메소드 앞에 액세스 수정자를 넣지 않으면 개인용 패키지라고합니다.
다음 예를보십시오.

package odp.proj;
public class A
{
    void launchA() { }
}

package odp.proj.test;
public class B
{
    void launchB() { }
}

public class Test
{
    public void test()
    {
        A a = new A();
        a.launchA()    // cannot call launchA because it is not visible
    }
}

PackageVisibleHelper 클래스를 사용하여 PackageVisibleHelperFactory가 고정되기 전에 비공개로 유지하면 어디서나 launchA (by PackageVisibleHelper) 메소드를 호출 할 수 있습니다.)

package odp.proj;
public class A
 {
    void launchA() { }
}

public class PackageVisibleHelper {

    private final PackageVisibleHelperFactory factory;

    public PackageVisibleHelper(PackageVisibleHelperFactory factory) {
        super();
        this.factory = factory;
    }

    public void launchA(A a) {
        if (factory == PackageVisibleHelperFactory.INSTNACNE && !factory.isSampleHelper(this)) {
            throw new IllegalAccessError("wrong PackageVisibleHelper ");
        }
        a.launchA();
    }
}


public class PackageVisibleHelperFactory {

    public static final PackageVisibleHelperFactory INSTNACNE = new PackageVisibleHelperFactory();

    private static final PackageVisibleHelper HELPER = new PackageVisibleHelper(INSTNACNE);

    private PackageVisibleHelperFactory() {
        super();
    }

    private boolean frozened;

    public PackageVisibleHelper getHelperBeforeFrozen() {
        if (frozened) {
            throw new IllegalAccessError("please invoke before frozen!");
        }
        return HELPER;
    }

    public void frozen() {
        frozened = true;
    }

    public boolean isSampleHelper(PackageVisibleHelper helper) {
        return HELPER.equals(helper);
    }
}
package odp.proj.test;

import odp.proj.A;
import odp.proj.PackageVisibleHelper;
import odp.proj.PackageVisibleHelperFactory;

public class Test {

    public static void main(String[] args) {

        final PackageVisibleHelper helper = PackageVisibleHelperFactory.INSTNACNE.getHelperBeforeFrozen();
        PackageVisibleHelperFactory.INSTNACNE.frozen();


        A a = new A();
        helper.launchA(a);

        // illegal access       
        new PackageVisibleHelper(PackageVisibleHelperFactory.INSTNACNE).launchA(a); 
    }
}

참고URL : https://stackoverflow.com/questions/1967229/java-subpackage-visibility

반응형