2011-08-14 7 views
5

JVMは、一致しないパラメータを含むメソッドをオーバーロードすると、引数よりも小さい引数を持つメソッドを常に使用します。var-argsによるメソッドのオーバーロード - ボクシングと拡大と組み合わせた

私は次の2つの例で上記を確認している:

拡幅:

class ScjpTest{ 

    static void go(int x){System.out.println("In Int");} 
    static void go(long x){System.out.println("In long");} 

    public static void main (String[] args){ 

     byte b = 5; 

     go(b); 

    } 

}

ボクシングをintに広がっバイト:整数

class ScjpTest{ 

    static void go(Integer x){System.out.println("In Int");} 
    static void go(Long x){System.out.println("In Long");} 

    public static void main (String[] args){ 

     int b = 5; 

     go(b); 

    } 

} 

箱入りintです上記の両方の例は正しい "In Int"を出力します。次の例に示すように、状況は上記

class ScjpTest{ 

    static void go(int... x){System.out.println("In Int");} 
    static void go(long... x){System.out.println("In lInt");} 

    public static void main (String[] args){ 

     byte b = 5; //or even with: int b = 5 

     go(b); 

    } 

} 

VAR-引数を伴うとき、私はかかわらず、混乱しています、次のエラー生成:

ScjpTest.java:14: reference to go is ambiguous, both method go(int...) in ScjpTest and method go(long...) in ScjpTest match 
       go(b); 
       ^
1 error 

をなぜそれが以前と同じルールを適用しません。例?バイトよりも大きい最小値であるため、バイトをintに拡大しますか?

+0

オンJava 7では、最後の例がうまくいきます。 – toto2

答えて

5

VAR-引数構文は、引数として配列を渡すだけに別名である:

foo(int ... arg)foo(int[] arg)

に等しいしかし、アレイは、階層ではありません。 String[]Object[]のサブクラスではありません。メソッドの引数には、まったく同じルールが関係します。したがって、コンパイラは、byteを渡すときにlong[]int[]を受け入れる2つのオーバーロードされたメソッドを区別できません。

+0

違う。 String []はObject []のサブクラスです。配列はJavaでは共変です(ただしジェネリックではありません)。私の答えを見てください:それは実際には動作しない古いJavaバージョンのバグです。 ziggyの例はJava 7で動作します。 – toto2

+0

...実際には、この例では、配列の継承ではなく、プリミティブ型の変換を拡大しています。 – toto2

1

実際にJava 7で動作します:varargsの例でも "In Int"を返します。以前のバージョンでは欠けていた機能だったと思います。私はあなたが使用しているJavaのバージョンが分からないかもしれませんが、おそらくJava 6のために働いているかもしれません。

しかし、私は最初の例でも動作します(varargsなし)。私は、原始的な広がりの転換を認識していませんでした。 ところで、最初の例と最後の例は、Byte、Integer、Longを使用すると失敗します。それらの型の間に階層がないからです(Numberのすべてのサブクラスを除く)。

1

AlexRが指摘したように、var-argsは配列のようなものです。プリミティブの配列は、(のようなbyte[] short[] int[] long[] float[] double[]は内部で同じクラスにコンパイルされているように見えるあなたのオーバーロードされたメソッドが曖昧である理由ですが、次のコードは、完全に有効である:。。
static void go(int... x){System.out.println("In Int");}
static void go(Long... x){System.out.println("In lInt");}

これは、正常にコンパイル(異なるタイプのint[]のでLong[]) 、および出力In Intを生成します。
あなたはSCJPのための準備をしている場合、私は非常にあなたが本SCJP Sun Certified Programmer for Java 6 Exam 310-065を読んで推薦する。この本の中でのオーバーロードセクションはボクシングとVAR-引数を混合しながら、すべてのトリックをカバーしています。

関連する問題