2

Javaによると、インスタンスメソッドの解決は、引数の実行時タイプに基づいています。

ただし、インスタンス変数を解決する際には、以下に示すように異なるアプローチを使用します。

プログラムの出力は..

Child
Parent
ParentNonStatic

ここで、最初の出力は引数の実行時タイプに基づいていますが、3番目の出力はそうではありません。

誰かがこれについて説明できますか?

  public class Child extends Parent {

        public static String foo = "Child";
        public String hoo = "ChildNonStatic";

        private Child() {
            super(1);
        }

        @Override
        String please() {
            return "Child";
        }

        public static void main(String[] args) {
            Parent p = new Parent();
            Child c = new Child();

           //Resolving method
            System.out.println(((Parent) c).please());

           //Resolving Static Variable
            System.out.println(((Parent) c).foo);

           //Resolving Instance Variable
            System.out.println(((Parent) c).hoo);
        }
    }
class Parent {

    public static String foo = "Parent";
    public String hoo = "ParentNonStatic";

    public Parent(int a) {
    }

    public Parent() {
    }

    String please() {
        return "Tree";
    }
}
4

3 に答える 3

6

オブジェクトをアップキャストする場合、参照しているアイテムのコンテンツを実際に変更するのではなく、処理方法だけを変更します。したがって、cを親にアップキャストしてplease()を呼び出すと、親に対してplease()が呼び出されますが、動的型はまだ子であるため、実際に呼び出されるのは子のオーバーライドされたバージョンであり、「子」が出力されます。

cをアップキャストしてfooを参照する場合、関数呼び出しを行っていません。コンパイラは、コンパイル時に何を参照しているかを判断できます。この場合、親型を持つオブジェクトのフィールドfooです。フィールドと静的フィールドはオーバーライドされません。代わりに、それらは隠されています。このアップキャストで実際に行うことは、Javaが子からではなく、非表示のバージョン(親からのもの)を選択するのを支援することです。同様に、hooを使用すると、親のバージョンを取得できます。

JAvaチュートリアルの情報は次のとおりです。http://java.sun.com/docs/books/tutorial/java/IandI/hidevariables.html

于 2009-11-05T02:52:00.983 に答える
2

Javaでは、実際には「キャスト」しません。オブジェクトをそのタイプにキャストできるかどうかを確認する以外は、キャストを要求してもJavaは実際には何もしません。したがって、キャストが「ClassCastException」をスローする可能性があります。

ただし、コンパイラはキャストを理解するため、キャストを使用してメソッド呼び出しが適切であることを検証します。

静的フィールドに関しては、コンパイラは実際にインスタンス変数を削除し、戻りタイプが何であれ、クラスを介してフィールドを参照します。

Parent p = new Parent();
Child c = new Child(); 
Parent pc = new Child();

System.out.println(c.foo); // will print Child
System.out.println(p.foo); // will print Parent
System.out.println(pc.foo); // will print Parent
System.out.println(((Child)pc).foo) // will print Child

フィールドは同じように機能するようです。

一言で言えば、Javaはメソッドに対して動的バインディングを実行し、フィールドに対して静的バインディングを実行すると思います。

于 2009-11-05T13:41:50.820 に答える
0

メソッドと同じようにフィールドがオーバーライドされることはありません。cをParentにキャストすると、「。hoo」が子のフィールドではなく、親の「hoo」フィールドを参照していることを示します。(より技術的に正しい方法で言えば、フィールドアクセスは多形ではありません。)

于 2009-11-05T02:45:09.610 に答える