9

2005年4月のSybexCompleteJava 2認定研究ガイド(ISBN0782144195)を読んでいます。この本は、Java認定に合格したいJava開発者を対象としています。

アクセス修飾子(および他の修飾子)に関する章の後で、次の質問(#17)を見つけました:

正誤問題:クラスYがクラスXを拡張し、2つのクラスが異なるパッケージにあり、クラスXにabby()という保護されたメソッドがある場合、Yの任意のインスタンスがYの他のインスタンスのabby()メソッドを呼び出すことができる。

この質問は私を少し混乱させました。

私の知る限り、同じクラス(またはサブクラス)の任意の変数で保護されたメソッドを呼び出すことができます。階層の上位にある変数(実装するインターフェースなど)で呼び出すことはできません。

たとえば、オブジェクトを継承したからといって、オブジェクトのクローンを作成することはできません。

しかし、質問は変数型については何も述べておらず、インスタンス型についてのみ述べています。

少し戸惑い、「本当」と答えました。

本の答えは

誤り。別のパッケージのスーパークラスから保護されたメソッドを継承するオブジェクトは、それ自体でそのメソッドを呼び出すことができますが、同じクラスの他のインスタンスでは呼び出すことはできません。

ここでは、変数タイプについては何もありません。インスタンスタイプについてのみです。

これは非常に奇妙です、私はそれを理解していません。

誰かがここで何が起こっているのか説明できますか?

4

6 に答える 6

2

正誤問題:クラスYがクラスXを拡張し、2つのクラスが異なるパッケージにあり、クラスXにabby()という保護されたメソッドがある場合、Yの任意のインスタンスがYの他のインスタンスのabby()メソッドを呼び出すことができる。

「誤り。別のパッケージのスーパークラスから保護されたメソッドを継承するオブジェクトは、それ自体でそのメソッドを呼び出すことができますが、同じクラスの他のインスタンスでは呼び出すことができません」。

BalusCが行ったように、それを書き留めて、Yの他のインスタンスのabby()を呼び出すメソッドをYに追加しましょう。

package one;
public class X {
    protected void abby() {
    }
}

package other;
import one.X;
public class Y extends X {
    public void callAbbyOf(Y anyOther) {
        anyOther.abby();
    }
}

Yは、参照を持つYの任意のインスタンスのabby()メソッドを呼び出すことできます。したがって、本の答えは明らかに間違っています。Javaにはインスタンス固有のスコープがありません(たとえば、インスタンスプライベートスコープを持つScalaとは異なります)。

慈悲深くしようとすると、おそらくメモリ内にあるYのインスタンスのメソッドにアクセスできる「Yの他のインスタンスと言うことを意味する質問です。Javaにはダイレクトメモリがないため、これは不可能です。アクセス。しかし、その場合、質問の言い回しが非常に悪いため、次のように答えることもできます。「誤り。別のJVMにあるインスタンス、ガベージコレクションされたインスタンス、または1つが停止したJVMのインスタンスでメソッドを呼び出すことはできません。一年前など」

于 2010-02-11T13:59:27.067 に答える
1

Java言語仕様から:

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

保護されたメンバーmが宣言されているクラスをCとします。アクセスは、CのサブクラスSの本体内でのみ許可されます。さらに、Idがインスタンスフィールドまたはインスタンスメソッドを示す場合、次のようになります。

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

したがって、保護されたメンバーはSのすべてのインスタンスでアクセス可能であり、あなたの本の答えはちょうど間違っています。

于 2010-02-11T19:37:43.287 に答える
0

私はその質問が次のことを意味していることをほぼ確信しています:

「Yの任意のインスタンスは、Xの他のインスタンスのabbey()メソッドを呼び出すことができます」(Yではありません)。

その場合、それは確かに失敗します。上記の別の回答から例を借りるには、次のようにします。

package one;
public class X {
    protected void abby() {
    }
}

package other;
import one.X;
public class Y extends X {
    public void callAbbyOf(X anyOther) {
        anyOther.abby();
    }
}

コンパイルに失敗します。

Java言語仕様では、その理由をここで説明しています:http: //java.sun.com/docs/books/jls/third_edition/html/names.html#6.6.2

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

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

于 2010-03-09T03:34:01.737 に答える
0

正誤問題:クラスYがクラスXを拡張し、2つのクラスが異なるパッケージにあり、クラスXにabby()という保護されたメソッドがある場合、Yの任意のインスタンスがYの他のインスタンスのabby()メソッドを呼び出すことができる。

それを描きましょう。

クラスX:

package one;
public class X {
    protected void abby() {}
}

クラスY:

package other;
public class Y extends X {}

テストケース:

public static void main(String[] args) {
    Y y1 = new Y();
    Y y2 = new Y();
    Y y3 = new Y();
    // ...
}

今、質問を読み直してください:、、などをy1呼び出すことができますか?、、などの電話もかけますか?abby()y2y3abby()y1y2y3

今後の質問については、ペンと紙をつかんで、文字通り質問を解釈してみてください。そのような模擬質問にはかなりの穴があります。

于 2010-02-11T13:27:55.150 に答える
0

その質問はひどい言い回しのようです-そして非常にまれなエッジケースについて尋ねます(SCJPテストでカバーされているかどうかさえわかりません)。それが表現されている方法はあなたの答えを正しくし、与えられた答えを正しくしません。同様の構造をコーディングして実行すると、これが簡単に証明されます...

package inside;

public class Base {

    private String name;

    public Base(String name)  {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    protected String abby(String name) {
        String old = this.name;
        this.name = name;
        return old;
    }
}




package outside;
import inside.Base;

public class Another extends Base {

    public Another(String name) {
        super(name);
    }

    public String setAnother(Another another, String hack) {
        return another.abby(hack);
    }

    public static void doCrazyStuff() {
        Another one = new Another("one");
        Another two = new Another("two");

        one.abby("Hi one"); 
        two.abby("Hi two");
        one.setAnother(two, "Hi two from one");

        System.out.println("one = " + one.getName());
        System.out.println("two = " + two.getName());

    }

    public static void main(String[] args) {
        Another.doCrazyStuff();
    }
}
于 2010-02-11T13:36:05.710 に答える
0

なぜなら、変数の型は、質問の文脈で「正気」になるまでここでは無関係だからです。メソッドabby()はに属しているX(そしてそれをY継承している)ので、Yのインスタンスを参照する型変数が宣言されているかどうかは関係ありません。どちらでもかまいませXY。アクセスabby()可能であるため、両方の変数を介して呼び出すことができます。

X myY1 = new Y();
myY1.abby();

Y myY2 = new Y();
myY2.abby();
于 2010-02-11T13:36:58.360 に答える