12

私は SCJP (最近、Oracle によって OCPJP としてブランド変更されました) の準備をしていますが、模擬試験で間違った特定の問題の 1 つが私を混乱させました。回答の説明では物事が十分に明確に説明されていません。

これは質問です:

class A 
{
    int x = 5;
} 
class B extends A 
{
    int x = 6;
} 
public class CovariantTest 
{
    public A getObject() 
    {
       return new A();
    } 
    public static void main(String[]args) 
    {
       CovariantTest c1 = new SubCovariantTest();
       System.out.println(c1.getObject().x);
    }
}

class SubCovariantTest extends CovariantTest 
{
    public B getObject() 
    {
       return new B();
    }
}

答えは です5が、私は を選び6ました。

オーバーライドは変数ではなく実行時のメソッドに適用されることを理解していますが、私の心がそれを解釈した方法は次のprintlnとおりです。

  1. c1 で getObject を呼び出す
  2. c1 は実際にはSubCovariantTestオブジェクトであり、 に対して有効なオーバーライドがgetObject()あるため、オーバーライドされたメソッドを使用します
  3. オーバーライドは B を返すので、6 である B から x を取得します。

JVMがその部分を無視し、コンパイル時に変数が関連付けられているためgetObject()、常に取得xする場合ですか?c1

4

6 に答える 6

4

ここで起こっていることの専門用語は「隠す」です。Javaの変数名は、参照しているオブジェクトではなく、参照タイプによって解決されます。

  • オブジェクトにはAx変数があります。
  • BオブジェクトにはAx変数とBx変数の両方があります。

ただし、同じシグニチャを持つインスタンスメソッドは「非表示」ではなく「オーバーライド」され、外部からオーバーライドされたバージョンのメソッドにアクセスすることはできません。

非表示は、同じシグニチャを持つ静的メソッドにも適用されることに注意してください。

簡略化された形式の模擬質問(オーバーライドなし):

class A {
    int x = 5;
}

class B extends A {
    int x = 6;
}

public class CovariantTest {

    public static void main(String[] args) {

        A a = new B();
        B b = new B();
        System.out.println(a.x); // prints 5
        System.out.println(b.x); // prints 6

    }
}
于 2012-10-23T13:07:19.477 に答える
0

メソッドがオーバーライドされるとサブクラスのメソッドが呼び出され、変数がオーバーライドされるとスーパークラスの変数が使用されます

于 2016-09-14T13:45:29.793 に答える