2015-11-01 9 views
11

を選択し、配列を可変引数なぜここに2つの異なる出力があるのか​​という疑問があります。
Integer[]は、ObjectObject[]の両方に暗黙的にキャストできます。オーバーロードは、私は2つのオーバーロードされたメソッドを持っている方法

+2

シャーロック[15.12.2.5。最も具体的な方法の選択](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5) – Pshemo

+0

少なくとも、コンパイラの警告が必要です。 –

+0

@Colonel、そうすることができますし、はいできます。試してみるとランタイム例外が発生します。 –

答えて

3

これは基本的にコンパイラの中で最も具体的なメソッドを呼び出すことを決定します。

あなたはvaragsで指定され、それがInteger[][]引数とObject[][]のparamとない方法でメソッドの呼び出しJVM委譲ため、実行時にfoo(Integer[]... args)

を呼び出します

System.out.println(foo(i));//Object[]... vs Integer[]... 

を呼び出します。 Object [] []ではなくInteger [] []でメソッドを呼び出す方がより具体的です。後で声明の中で


あなたはそれがvaragsを使用して再度bar(Object... args)

に行きます

System.out.println(bar(i));//Object... vs Integer[]...

を呼び出すときに、PARAMの種類は[]オブジェクトではなくなりますオブジェクト[] []。コンパイラは、Object... argsを持つ最も具体的なメソッドを呼び出します。

次のとおりvaragsを除去することにより、メソッドのシグネチャを変更する場合:

//Object... vs Integer[]... 
    public static String bar(Object args) { 

     return "Object args"; 
    } 

    public static String bar(Integer[] args) { 
     return "Integer[] args"; 
    } 

を、あなたはそれがメソッドの呼び出しに、より具体的であるとして、それはbar(Integer[] args)を呼び出すことがわかります。

JLS Subtyping among Array Types

だから当たり、より正確には、

  • SとTの両方の基準型である場合は、[]> T [] IFF S> S T.
  • OBJECT>オブジェクト[]

これは整数のコール[]は整数の[] []としない[] []オブジェクトを有する方法について説明することを意味します。 Integer [] []ではなく、Object []に対してInteger []の呼び出しが行われます。

最も具体的な方法を選択するには、hereを参照してください。

3

最初のケースでは、argsの型は実際はInteger [] []です。つまり、あなたの配列はvarargsによって別の配列に囲まれています。コンパイラはInteger []バージョンを選択します。最も具体的な型です。

2番目のケースでは、args == iとなり、Integer []です。この場合、コンパイラはInteger [] ...バージョンを呼び出すために新しい配列にラップするか、Integer []をObject []にキャストするかのいずれかを選択する必要がありました。それはルールなので、2番目のものを選んだ。

ストーリーのモラルは次のようなものです。varargsメソッドをオーバーロードしないでください。混乱します。

+1

「それはルールです」という仕様のビットを見つけることができますか? –

+0

私は...できますが、OPはすでに彼のコンパイラでそれを証明しています:) –

+0

もし見つけられたら、私はupvoteします。私はそれを解読することに問題があります。 –

関連する問題