web-dev-qa-db-ja.com

パッケージ外で保護されたコンストラクターを使用できないのはなぜですか?

このコードの部分で、パッケージの外部で保護されたコンストラクターを使用できないのはなぜですか。

package code;
public class Example{
    protected Example(){}
    ...
}

Check.Java

package test;
public class Check extends Example {
  void m1() {
     Example ex=new Example(); //compilation error
  }
}
  1. クラスを拡張したにもかかわらずエラーが発生するのはなぜですか?説明してください

編集:

コンパイルエラー:

コンストラクタExample()は表示されません

35
Abhilash28

protected修飾子は、パッケージ内およびパッケージ外のサブクラスでのみ使用されます。 Example ex=new Example();を使用してオブジェクトを作成すると、デフォルトで親クラスのコンストラクターが呼び出されます。

保護されている親クラスコンストラクターとして、コンパイル時エラーが発生します。以下の例2に示すように、JSL 6.6.2.2に従って保護されたコンストラクターを呼び出す必要があります。

package Super;

public class SuperConstructorCall {

    protected SuperConstructorCall() {
    }

}

package Child;

import Super.SuperConstructorCall;

public class ChildCall extends SuperConstructorCall
{

    public static void main(String[] args) {

        SuperConstructorCall s = new SuperConstructorCall(); // Compile time error saying SuperConstructorCall() has protected access in SuperConstructorCall
    }
}

JLS 6.6.2.2 に準拠する例2:

package Super;

    public class SuperConstructorCall {

    protected SuperConstructorCall() {
    }

}

package Child;

import Super.SuperConstructorCall;

public class ChildCall extends SuperConstructorCall
{

    public static void main(String[] args) {

        SuperConstructorCall s = new SuperConstructorCall(){}; // This will work as the access is by an anonymous class instance creation expression 
    }
}
6
kittu

通常、protectedは、同じパッケージ内のサブクラスまたはクラスのみがアクセスできることを意味します。ただし、JLSからのコンストラクターのルールは次のとおりです。

6.6.2.2。保護されたコンストラクターへの修飾されたアクセス

保護されたコンストラクターが宣言されているクラスをCとし、保護されたコンストラクターの使用が発生する宣言の最も内側のクラスをSとします。次に:

アクセスがスーパークラスコンストラクター呼び出しsuper(...)、または修飾されたスーパークラスコンストラクター呼び出しE.super(...)による場合(Eは1次式)、アクセスは許可されます。

アクセスが匿名クラスインスタンス作成式new C(...){...}、または修飾された匿名クラスインスタンス作成式E.new C(...){...}である場合、Eは一次式の場合、アクセスが許可されます。

アクセスが単純なクラスインスタンス作成式new C(...)、または修飾されたクラスインスタンス作成式E.new C(...)である場合、Eはプライマリ式、またはメソッド参照式Cです。 :new、CはClassType、アクセスは許可されません。保護されたコンストラクターは、クラスインスタンス作成式(匿名クラスを宣言しない)またはメソッド参照式によって、それが定義されているパッケージ内からのみアクセスできます。

例として、これはコンパイルされません

public class Example extends Exception {

    void method() {
        Exception e = new Exception("Hello", null, false, false);
    }
}

しかし、これは

public class Example extends Exception {

    Example() {
        super("Hello", null, false, false);
    }
}

これもそうです

public class Example {

    void method() {
        Exception e = new Exception("Hello", null, false, false) {};
    }
}

ルールは明確ですが、その背後にある理由が理解できたとは言えません!

14
Paul Boddington

実際、Checkには暗黙のコンストラクターと暗黙のExampleコンストラクター呼び出しがあるため、すでにExampleの保護されたコンストラクターを使用しています。

public Check() {
    super();
}
3