12

このキーワードprotectedは、同じパッケージおよびサブクラス内のクラスへのアクセスを許可します ( http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html )。

現在、すべてのクラスはjava.lang.Objectスーパークラス ( http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html ) として持っています。

java.lang.Objectしたがって、すべてのクラスがのメソッドにアクセスできると結論付けますprotected

次の例を見てください。

パブリック クラス テストクラス {
  public Object getOne() は CloneNotSupportedException をスローします {
    this.clone(); を返します。
  }
  public Object getTwo() は CloneNotSupportedException をスローします {
    return ((オブジェクト) this).clone();
  }
}

正常にgetOne()コンパイルされますgetTwo()が、

Testclass.java:6: clone() は java.lang.Object でアクセスを保護しています
        return ((オブジェクト) this).clone();

がコンパイルされない理由も、( s メンバーgetTwo()のアクセスに関して) との違いもわかりません。java.lang.ObjectgetOne()

4

3 に答える 3

16

参照している式のコンパイル時の型が独自のクラスまたはサブクラスである場合にのみ、別のパッケージ内の型の保護されたメンバーにアクセスできます。(「あなたの」クラスはコードを含むクラスです。)あなた自身のクラスも、メソッドを最初に宣言したタイプのサブクラスでなければなりません。

以下に例を示します。Base他のすべてのクラスとは異なるパッケージにあると仮定します。

package first;
public class Base
{
    protected void Foo() {}
}

// Yes, each class is really in its own file normally - but treat
// all the classes below as being in package "second"

package second;
public class Child extends Base
{
    public void OtherMethod(Object x)
    {
        ((Base) x).Foo(); // Invalid: Base is not Child or subclass
        ((Child) x).Foo(); // Valid: Child is Child
        ((GrandChild) x).Foo(); // Valid: GrandChild is subclass of Child
        ((OtherChild) x).Foo(); // Invalid: OtherChild is not Child or subclass
    }
}

public class GrandChild extends Child {}
public class OtherChild extends Base {}

つまり、「あなたに似たオブジェクト」の保護されたメンバーにアクセスできるようになります。

詳細は、Java 言語仕様のセクション 6.6.2 にあります

オブジェクトのprotectedメンバーまたはコンストラクターは、そのオブジェクトの実装を担当するコードによってのみ宣言されているパッケージの外部からアクセスできます。

6.6.2.1 保護されたメンバーへのアクセス

保護されたメンバーmが宣言されているクラスをCとします。アクセスは、 CのサブクラスSの本体内でのみ許可されます。さらに、 Id がインスタンス フィールドまたはインスタンス メソッドを表す場合: アクセスが修飾名Q.Idによる場合 ( QExpressionName )、式Qの型がSである場合にのみ、アクセスが許可されます。またはSのサブクラス 。アクセスがフィールド アクセス式E.Idによるものである場合、Eプライマリです。 式、またはメソッド呼び出し式E.Id(. . .) ( Eプライマリ 式) によってアクセスが許可されるのは、 Eの型 がSまたはSのサブクラスである場合に限られます。

于 2009-01-16T19:47:05.127 に答える
5

「 」と言ったとき((Object) this).clone()、スーパークラス Object を介して独自のオブジェクトにアクセスしました。オブジェクトへの拡張変換を実行しました。次に、コードは Object で clone を呼び出そうとします。

ただし、既に指摘したように、clone は保護されたメソッドです。つまり、オブジェクトが java.lang の同じパッケージにある場合にのみ、OBJECT の clone メソッドにアクセスできます。

this.clone と言うと、クラスはオブジェクトを拡張したため、継承のために保護されたクラス修飾子を介して直接オーバーライドまたはクローンを使用することができました。しかし、それはオブジェクトの実装を変更しません。

((Object) yourObject) と言うと、Object クラスを介してのみアクセスできるものを取得できます。Object クラスのパブリック メソッドのみが、パッケージ java.lang の外部からアクセスできるため、コンパイラがこれを認識しているため、コンパイル時に例外が発生します。

this.clone() と言うと、Object を介して継承したオブジェクトの clone メソッドを呼び出すことになり、カスタム サブクラスの一部になるため呼び出すことができるようになります。

于 2009-01-16T19:46:47.827 に答える
1

違いは、Object.clone() へのアクセス方法です。clone は、同じパッケージ内のサブクラスまたはクラスを介してアクセスした場合にのみアクセスできます。getOne() の例では、this.clone() を呼び出しています。これは明らかにサブクラス内からのアクセスを満たします。

getTwo() では、TestClass.clone() ではなくObject.clone() にアクセスしています。これが機能するためには、オブジェクトへのパッケージレベルのアクセスが必要であり、それが原因でエラーが発生します。

于 2009-01-16T19:51:03.717 に答える