私は2つの関数を作成したいと思います
long min(long...);
int min(int...);
しかし、2番目の、つまりmin(1, 5)
1つを呼び出そうとすると、あいまいなメソッド呼び出しが発生します
名前を変更する以外の回避策はありますか?
私は2つの関数を作成したいと思います
long min(long...);
int min(int...);
しかし、2番目の、つまりmin(1, 5)
1つを呼び出そうとすると、あいまいなメソッド呼び出しが発生します
名前を変更する以外の回避策はありますか?
既知のバグです
あなたが説明する動作は、Java 7 で修正されたバグです。詳細については、リリース ノートの「最も具体的な Varargs メソッドの選択の変更」というセクションを参照してください。
コンパイルする理由
可変アリティは、最も具体的な方法を決定する際に最後に来ます。複数ある場合にどの vararg メソッドが適用されるかを決定するルールは、JLS 15.12.2.4で定義されています。
次のいずれかの場合、m という名前の可変アリティ メンバ メソッドは、同じ名前の別の可変アリティ メンバ メソッドよりも具体的
です
。
- 最初のメソッドのパラメーターの型は、U1、...、Uk-1、Uk[] です。
- もう一方のメソッドのパラメータの型は、T1、...、Tn-1、Tn[] です。
- 1 から n までのすべての j に対して、Uj <: Tj
あなたの場合、k = n、およびU1[] = int[]
その逆T1[] = long[]
かどうかの決定を下すことができます。int <: long
つまり、考慮される型はint[]
vslong[]
ではなくint
vslong
です。そのint <: long
ため、int...
メソッドを選択してコンパイルする必要があります。
結論:
このコードは、Java 7 では正常にコンパイルされるはずですが、Java 5 または 6 ではコンパイルされません。以下のコードはint
、Java 7 で出力されます。
public class Test1 {
public static void main(String[] args) {
new Test1().m(1, 2);
}
int m(int... i) {
System.out.println("int");
return 0;
}
long m(long... i) {
System.out.println("long");
return 0;
}
}
これを試して
public class Test {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
new Test().m(100L,512L);
new Test().m(100,512);
}
int m(int... i) {
System.out.println("int");
return 0;
}
long m(long... i) {
System.out.println("long");
return 0;
}
}
問題は、これらのメソッドを で呼び出すと、使用したようにinteger
、どのメソッドも引数に完全に一致しないことですvar-args
。また、どちらもコンマで区切られた値を引数としてvar-args
取ることができます。int
したがって、ambiguous method
エラー。
オーバーロードされたメソッドを呼び出すときCompiler
は、最初のメソッドを選択しexact match
ます。次に、nearest type
キャストします。
現在、var-args
は単なる であるため、コンパイラは値array
を渡すときに使用する配列を決定できません。として、どちらの配列もまたはinteger
と見なすことはできません。したがって、呼び出し可能なメソッドの両方が必要です。exact match
nearest conversion
method invocation
の場合には、さらに多くのルールがありますOverloading
。からそれらを学ぶことができますJava Language Specification
。
@assylias answerのように、この問題は Java 7 で修正されました。ただし、Java バージョン < 7 では機能しません。
これらのメソッド シグネチャは一意であり、有効なメソッド オーバーロードです。
問題はメソッド呼び出しの引数にあるはずです。私の推測では、次のようなリテラルでメソッドを呼び出していると思います。
min(100)
100 は整数リテラルであるため、これは好ましくありませんが、自動的に long に変換されます。
長いリテラルの最後に L を使用してメソッド呼び出しを明確にすると、問題が解決するはずです。
min(100L)
また、Java Object Integer と Long を使用して呼び出しを明示的に行い、プリミティブ型への変換を自動ボクシングに任せることもできます。
min(new Long(100))
min(new Integer(100))