web-dev-qa-db-ja.com

Java保護修飾子について

Package1にAというクラスと、package2にCという別のクラスがあります。クラスCはクラスAを拡張します。

Aには、次のように宣言されたインスタンス変数があります。

protected int protectedInt = 1;

これがクラスAのコードです

package package1;

public class A {

    public int publicInt = 1;
    private int privateInt = 1;
    int defaultInt = 1;
    protected int protectedInt = 1;

}

そして、これがクラスCのコードです。

package package2;
import package1.A;

public class C extends A{

    public void go(){
        //remember the import statement
        A a = new A();
        System.out.println(a.publicInt);
        System.out.println(a.protectedInt);

    }
}

EclipseはC.go()の最後の行に下線を引いており、「A.protectedInt」は表示されていません。これは、Oracleのドキュメントにある「保護された」キーワードの定義と矛盾するようです。

Protected修飾子は、メンバーが(package-privateと同様に)独自のパッケージ内でのみアクセスでき、さらに、別のパッケージ内のそのクラスのサブクラスによってのみアクセスできることを指定します。

何が起きてる?

37
mahela007

何が起きてる?

protectedの意味を誤解しました。 A内で宣言された保護されたメンバーには、C内からアクセスできますが、CのインスタンスまたはCのサブクラスに対してのみアクセスできます。保護されたアクセスの詳細については、 JLSのセクション6.6.2 を参照してください。特に:

保護されたメンバーが宣言されているクラスをCとします。アクセスは、CのサブクラスSの本体内でのみ許可されます。

さらに、Idがインスタンスフィールドまたはインスタンスメソッドを示す場合、次のようになります。

  • [...]

  • アクセスがフィールドアクセス式E.Id(Eはプライマリ式)、またはメソッド呼び出し式E.Id(。。。)(Eがプライマリ式)の場合、アクセスは許可されますEのタイプがSまたはSのサブクラスである場合に限ります。

(エンファシス鉱山。)

したがって、thisコードで問題ありません。

C c = new C();
System.out.println(c.publicInt);
System.out.println(c.protectedInt);
39
Jon Skeet

CAを継承しているため、CprotectedA変数を直接使用できます。

public class C extends A{

    public void go(){

       System.out.println(protectedInt);

    }
}

コードに従って、Aのインスタンスを作成し、protected変数そのインスタンスを介してにアクセスしています。これは、Javaのルールに違反します-保護された変数はパッケージの外には見えません

11
sanbhat
_ public void go(){
        //remember the import statement
        A a = new A();
        System.out.println(a.publicInt);
        System.out.println(a.protectedInt);

    }
_

A a = new A();および_a.protectedInt_を実行しているときに、Java標準に従って違法なAの保護されたメンバーにアクセスしようとしています

代わりに、直接_this.protectedInt_を実行できます。

3
Abhishek Singh

Protectedは次を意味します:

a)このメンバーは、オブジェクトの参照を通じて、同じパッケージ内のすべてのクラスにアクセスできます。

b)異なるパッケージの場合、これはAと言うBのサブクラス内でのみアクセス可能であり、使用される参照はBインスタンスまたはBの任意のサブクラスのものにすることができます。

例を見てみましょう:

Aをいくつかのパッケージの親クラスにしてみましょうcom.ex1 B、CをAとは異なるパッケージw.r.tのクラスとするcom.ex2。また、B extends AおよびC extends B。 B(Aのサブクラス)内でAの保護フィールドを使用する方法を見ていきます

Aのコード:

public class A {
    protected int a = 10;
}

Bのコード:

public class B extends A {


    public void printUsingInheritance() {
        // Using this
        System.out.println(this.a);
    }


    public void printUsingInstantiation() {
        // Using instance of B
        B b = new B();
        System.out.println(b.a);

        // Using instance of C as C is subclass of B
        C c = new C();
        System.out.println(c.a);


        A a = new A();
        System.out.println(a.a); // Compilation error as A is not subclass of B
    }
}

Cのコード:

public class C extends B {

}

protected Staticの場合:

同じ規則が適用されますが、b)では、Aのクラス参照によってAのすべてのサブクラスでアクセスできます。 参考

2
Number945

保護されたメンバーが宣言されている同じパッケージ内で、アクセスが許可されます。

package package1;

public class C extends A{
    public void go(){
        A a = new A();
        System.out.println(a.protectedInt);  // got printed 
        C c = new C();
        System.out.println(c.protectedInt);  // got printed as well
    }
}

保護されたメンバーが宣言されているパッケージの外では、そのオブジェクトの実装を担当するコードによってのみアクセスが許可されます。この場合、Cはそのオブジェクトの実装を担当するため、保護されたオブジェクトにアクセスできます。

package package2;

public class C extends A{
    public void go(){
        A a = new A();
        System.out.println(a.protectedInt);  // compiler complains  
        C c = new C();
        System.out.println(c.protectedInt);  // got printed
    }
} 
1
Ethan

Protection2クラス内にProtectionクラスをインスタンス化する必要はありません。 Protectionクラスをインスタンス化せずに、保護された変数を直接呼び出すことができます。 Protection2クラスはProtectionクラスを拡張するためです。したがって、変数はサブクラスによって自動的に継承されます。

以下のコードで試してください:

public class Protection2 extends Protection{
Protection2()
{System.out.println("n_pro = " +n_pro);
}}
1
Sugumar