私が呼ぶときa.displayName("Test")
、それはクラスアイスクリームのメソッドを呼び出します。displayName(String...s)
この方法は、可変引数に取ります。出力-
test Icecream
test Faloodeh
test Faloodeh: Faloodeh
test Faloodeh: Faloodeh
私は方法を変更する場合でも、displayName(String s)
(私はコード内のそのセクションをコメントアウトしている)、それはクラスファールーデのメソッドを呼び出します。新しい出力-
test Faloodeh
test Faloodeh
test Faloodeh: Faloodeh
test Faloodeh: Faloodeh
私はそれが起こるん理由を知りたいと思いました。
class Icecream{
public void displayName(String...s){
System.out.println(s[0]+" "+"Icecream");
}
/*public void displayName(String s){
System.out.println(s+" "+"Icecream");
}
*/
public void describe(String s) {
System.out.println(s+" "+"Icecream: Ice cream");
}
}
class Faloodeh extends Icecream {
public void displayName (String s){
System.out.println(s+" "+"Faloodeh ");
}
public void describe (String s) {
System.out.println(s+" "+"Faloodeh: Faloodeh");
}
}
class Test {
public static void main(String arg[]) {
Icecream a=new Faloodeh ();
Faloodeh b=( Faloodeh)a;
a.displayName("test");
b.displayName("test");
a.describe("test");
b.describe("test");
}
}
**編集 - **答えてくれてありがとう。別の疑いで私を助けてください。私はにコードを変更します -
class Icecream{
public void displayName(String s){
System.out.println(s+" "+"Icecream");
}
/*public void displayName(String s){
System.out.println(s+" "+"Icecream");
}
*/
public void describe(String s) {
System.out.println(s+" "+"Icecream: Ice cream");
}
}
class Faloodeh extends Icecream {
public void displayName (String...s){
System.out.println(s+" "+"Faloodeh ");
}
public void describe (String s) {
System.out.println(s+" "+"Faloodeh: Faloodeh");
}
}
class Test {
public static void main(String arg[]) {
Icecream a=new Faloodeh ();
Faloodeh b=( Faloodeh)a;
a.displayName("test");
b.displayName("test");
a.describe("test");
b.describe("test");
}
}
さて、これは次のように出力 - 与えます
test Icecream
test Icecream
test Faloodeh: Faloodeh
test Faloodeh: Faloodeh
あなたはすべて説明したように、ここでBは、クラスファールーデの目的です。そして、displayName(String...s)
クラスのファールーデはオーバーライドを取得していません。それでも出力で、それが表示さtest Icecream
なぜ?
ここで重要なポイントは変化するということであるdisplayName(String... s)
にdisplayName(String s)
原因displayName(String s)
でメソッドFaloodeh
にオーバーライドし、そのスーパークラスのメソッドを。
Icecream.displayName(String... s)
そしてFaloodeh.displayName(String s)
、彼らはお互いを上書きしないように、異なるシグネチャを持っています。しかし、一つを受け入れるように元を変更するString
だけで発生するオーバーライド原因と同じシグネチャを持つためにそれらの原因となります。
(:詳細はJavaでは、メソッド呼び出しは、大きく3つの段階で解決されているJLS 15.12、私はまた、より詳細に説明こちら):
- 適用可能な方法を検索するためのクラスを検索します。これは、あなたがメソッドを呼び出すされているオブジェクトのコンパイル時の型に基づいています。この場合は、
a
。a
コンパイル時の型があるIcecream
ので、唯一、Icecream
sの方法を考えます"。それが見つからないことに注意してくださいdisplayName
方法をFaloodeh
のコンパイル時の型があるためa
ですIcecream
。 - あなたが渡された引数に基づいて呼び出すメソッドのオーバーロードを決定します。ここで一つだけの選択肢があります。変更前と変更後の両方として、
displayName
あなたが渡された引数と互換性のある唯一のオーバーロードです。 - あなたがメソッドを呼び出しているオブジェクトの実行時の型に基づいて呼び出すメソッドのどの実装を決定します。
a
実行時の型がありますFaloodeh
。変更前、displayName
でオーバーライドされていないFaloodeh
、それはスーパークラスの実装を呼び出しますので、。変更後は、displayName
上書きされてしまう、そうで実装がFaloodeh
呼ばれています。
あなたの編集について:
コンパイル時の型があるため、この場合に、b
であるFaloodeh
、検索に対してクラスがあるFaloodeh
(ステップ1)。しかし、あなたが与えた引数(ステップ2)に一致する2つの方法があります。
displayName(String...)
ここで宣言されているFaloodeh
、と。displayName(String)
これは継承されています。
そのようなAの状況では、コンパイラは常に変数アリティせずに過負荷を好みます - displayName(String)
。これは、明らかに指定されているJLS§15.12.2。具体的には、ステップ2は、3つ以上のサブステップにさらに分割されます。最初のサブステップは、可変アリティ方法を可能にすることなく、方法を見つけようと、任意のサブステップは、任意の方法を発見した場合、残りのサブステップはスキップされます。