3

次のコードがあります。

import java.lang.*;

public class Program
{
    public static void main(String [] args) 
    { 
        B a = new A(); 

        a.p(10);  
        a.p(10.0); 
    } 
} 
    class B { 
        public void p(double i) 
        { 
            System.out.println(i*2); 
        } 
    }

    class A  extends B{ 
        public void p(int i) 
        { 
            System.out.println(i); 
        } 
    } 

を使用してこのコードを実行するとB a = new A()、両方のケースで 20.0 が得られます。オーバーロードは、コンパイラが宣言された型を調べて関数を適切に呼び出すコンパイル時に処理されるためです。宣言された型はクラス B だったので、どちらの場合もクラス B のメソッドが呼び出されました。もしそうならA a = new A();、両方の答えで10を得るはずですが、そうではありません。a.p(10)で 10と で 20.0 を取得していa.p(10.0)ます。静的バインディングの概念と、実際の型ではなく宣言された型を見る静的バインディングによって行われるオーバーロードの全体的な概念に基づいて、なぜ結果がこのように出てくるのでしょうか? 大変お世話になりました。

4

7 に答える 7

2

intを に拡張することはできますが、doubleその逆はできません。これは、or10を呼び出すことはできますが、and は暗黙的に ie に変換されず、ie のみが呼び出されることを意味します。B.p(double)A.p(int)10.0doubleintB.p(double)

于 2013-01-31T17:21:36.750 に答える
2

メソッドpはオーバーライドされたメソッドではないため、使用するとサブクラスに継承されます

Super sup = new Sub();
sup.p(int);
sup.p(double);

この場合、スーパークラスには double をパラメーターとして受け取るメソッドがあり、intはスーパークラスのメソッドに収まる可能性があるためdouble、double を受け入れるメソッドが呼び出されます。

Sub sup = new Sub();
sup.p(int);
sup.p(double);

ただし、この場合、サブクラスには double を取るメソッドがないためsup.p(double) call、引数として double を渡すと、スーパークラスから継承されたメソッドが使用されるためです。

于 2013-01-31T17:23:42.597 に答える
1

この反例は役立つかもしれません:

import java.lang.*;

public class X
{
    public static void main(String [] args) 
    { 
        B c = new A(); 

        c.p(10);  
        c.p(10.0); 
        c.p("AAA");
        ((A)c).p(10);
    } 
} 
    class B { 
        public void p(String s) 
        { 
            System.out.println("B: my string is " + s); 
        } 

       public void p(double i) 
        { 
            System.out.println("B: twice my double is: " + i*2); 
        } 
    }

    class A  extends B{ 
        public void p(int i) 
        { 
            System.out.println("A: my number is " + i); 
        } 
    } 

出力:

C:\temp>java X
B: twice my double is: 20.0
B: twice my double is: 20.0
B: my string is AAA
A: my number is 10

問題は次のとおりです。

1)タイプを「B」(「A」ではない)として宣言しています

2)Bp(10)は、浮動小数点引数としてintを受け入れることができます

3)したがって、それはあなたが得ているものです

これは、どのメソッドがオーバーロードまたはオーバーライドされるかではなく、どの引数タイプを暗黙的に変換できるかという問題です。

于 2013-01-31T17:25:54.187 に答える
1

オブジェクトがタイプを宣言すると、Javaではサブタイプが。であるため、引数と互換性があるためB、バージョンが呼び出されます。doubleintintdouble

オブジェクトがとして宣言されるとA、メソッドp()は2つのバージョンでオーバーロードされます。

p(int arg);
p(double arg);

したがって、を渡すと、intより正確であるため最初のバージョンが選択され、double2番目のバージョンを渡すと、最も具体的な署名であるために選択されます。

参考までに、§15.12.2の関連するJLSおよびGiladBrachaによるこの投稿を参照してください。ところで、すべてのプログラミング言語はエンジニアリングの努力であり、これはあなたが取るものに対してあなたが支払う代償があることを意味するので、あなたが最も論理的な方法であると思うことに基づいて言語がどのように振る舞うべきかを理解しようとしないでください。Javaの主な情報源はJLSであり、注意深く読むと、ソースコードの行があいまいでコンパイルできない場合もあることがわかります(驚くべきことに?)。

于 2013-01-31T17:29:48.227 に答える
1

あなたの場合、コンパイル時にバインドされるオーバーロードを実行しています(静的バインディング)。静的バインディングは、参照が指しているオブジェクトのタイプではなく、参照のタイプで発生します。最初のケースでは、Bの参照変数を使用し、それにAのオブジェクトを割り当てています。参照はBであるため、intを使用してもBのメソッドp(double)は静的にバインドされます(intは2倍に拡大)。

2番目のケースでは、参照をA自体として使用しています。この場合、2つのp()メソッドを使用できます。1つはBからのp(double)で、もう1つはAからのp(int)です。したがって、p(10)はpを呼び出します。 (int)とp(10.0)はp(double)を呼び出します

これを試して:

class B { 
    public void p(String i) 
    { 
        System.out.println("parent:"+i); 
    } 
}

class A  extends B{ 
    public void p(int i) 
    { 
        System.out.println(i); 
    } 
} 
public class Test1 {
    public static void main(String args[]) {

         A a = new A(); //arg
            a.p(10);  
            a.p("sample"); 
    }
}

argとマークされた行をBa= new A()に変更すると、どちらの場合もコンパイラが親pを呼び出そうとしていることがわかります。

于 2013-01-31T17:31:46.953 に答える
1

あなたが書くとき、2つのメソッドを持つA a = new A()type の新しいオブジェクトを作成します。と、そして を呼び出すと、変換が不足しているため呼び出されます。AA.p(int)B.p(double)A.p(10.0)B.p(double)

于 2013-01-31T17:24:48.090 に答える