2016-05-19 13 views
11

を呼び出すには、次のコード例を考えてみましょう:Javaのオーバーロード:参照を曖昧

public class TestClass { 

    public void doSth(String str, String l, Object... objects) { 
     System.out.println("A"); 
    } 

    public void doSth(String str, Object... objects) { 
     System.out.println("B"); 
    } 

} 

私は今、私が期待した結果Aを得るnew TestClass().doSth("foo", "bar")を呼び出すとき。私はプリミティブ型にパラメータlをchagingすることにより、第1の方法のメソッドシグネチャを変更した場合でも:new TestClass().doSth("foo", 2L)を呼び出す

public class TestClass { 

    public void doSth(String str, long l, Object... objects) { 
     System.out.println("A"); 
    } 

    public void doSth(String str, Object... objects) { 
     System.out.println("B"); 
    } 

} 

reference to call ambiguousコンパイル時エラーを生成します。

私は今、いくつかの時間のための1つについて考えともthis stackoverflow questionに相談が、私はこの問題が発生した理由を理解することができませんでした。私の意見では、doSth("foo", 2L)doSth(String string, long l, Object... obj)シグニチャに特有のものであり、コンパイラもこの結論に至るはずです。

+0

明らかにプリミティブはオブジェクトでもありますか? –

+0

@blahfunkは、はい、彼らが頭に浮かぶ唯一の説明は、[オートボクシング](https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html)ですが、これがあるべき – Andrew

+0

ラップすることができます1つの変換ステップは、メソッドの基本バージョンよりも「遠く」離れています。 – Turing85

答えて

5

この場合、自動ボクシングはあなたに悲しみを引き起こしています。皮肉なことに、その前にあなたは正しい - 「長い」バージョンが簡単に選ばれただろう。

基本的に、コンパイラは、それが当然のことながら、オブジェクトである、あなたの値からロングを作成することができることを知っています。だから、ロングバージョンとロングバージョンのどちらも使用できるので、まだ混乱しています。一つは他のものより "良い"ものですか?多分それはかなり良いラインです。この状態で

+1

まあ、[フェーズ1](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15。 html#jls-15.12.2)は、ボックス化またはボックス化解除変換*を許可せずに、過負荷解決を明示的に指定します。この段階では、自動ボクシングは行われません。この段階で 'doSth(String str、long l、Object ... objects)'を選択する必要があります。何か不足していますか? – Tunaki

+0

これは面白いです。 'doSth(long l)'と 'doSth(Object o)'のようなパラメータが1つしかないときに、なぜこれが混乱を引き起こさないのでしょうか? – Turing85

+3

@Tunaki Phase 1と2では、可変アリティメソッドも除外されているため、OPのメソッドのどちらもフェーズ3まで考慮されていません。不思議なことに、 'doSth(" foo "、2L、null)'はコンパイルされます。あなたのリンクで)状態。 – Radiodef

1

、私は唯一の正確な議論はそれがないように、Javaは、振る舞う理由として、私の観察ではなく報告することができます。

void doSth(long l) {...} 
void doSth(Object o) {...} 

に方法を変更まず

は、doSth(2L);が期待される結果をもたらす、すなわち、問題を取り除きます。 OPによって報告されているように、コールdoSth(2l);と共に

void doSth(long... ls) {...} 
void doSth(Object... os) {...} 

を可変引数する方法のパラメータを変更、さらに一歩行く

は同じコンパイルエラーをもたらします。この段階で

私の提案はオートボクシングと一緒に、アレイ内のパラメータをencapusaltingが混乱を引き起こすことです。 JLSに関する私の知識は、これを適切に説明するのに十分なものではありません。

関連する問題