4

私は Java を学んでいて、オーバーロードに関するいくつかの質問に答えました。例として、次の関数の使用を取り上げます。

f('a', 'a');

次の 2 つの定義があるとします。

static void f(int i, char j){
    System.out.println("int_char");
}

static void f(double i, char j){
    System.out.println("double_char");
}

大丈夫でしょう。すべての 2 番目のパラメーターが正確に一致するためです。しかし、最初のパラメーターは、両方とも widen を使用します。char の拡大順序は次のとおりです。

char -> int -> long -> float -> double

char が int を達成するには、1 つのステップが必要です。ただし、2 倍にするためには 4 つのステップが必要です。したがって、結果は次のとおりです。

int_char

ただし、パラメーターの順序を次のように変更します。

static void f(int i, char j){
    System.out.println("int_char");
}

static void f(char i, double j){
    System.out.println("char_double");
}

コンパイラはエラーをあいまいなものとして提案します。なんで?

別のケースは次のとおりです。

static void f(char i, Character j){
    System.out.println("char_Character");
}

static void f(Character i, Character j){
    System.out.println("Character_Character");
}

2 番目のパラメーターは両方とも atuoboxing を使用します。しかし、 void f(char i, Character j) の最初のパラメーターは完全に一致しています。これら 2 つの機能が一緒になって曖昧になるのはなぜですか?

最後に、これらの関数のいずれかが次のように表示された場合:

static void f(Character... i){
    System.out.println("Character_varargs");
}

widen > boxing > varargs であるため、出力は Character_varargs ではありません。しかし、Character_varargs に 2 つのあいまいな関数がある場合は、次のようになります。

static void f(char i, Character j){
    System.out.println("char_Character");
}

static void f(Character i, Character j){
    System.out.println("Character_Character");
}

static void f(Character... i){
    System.out.println("Character_varargs");
}

結果は Character_varargs になります。なんで?

次のような、明確で優先度の高いオーバーロード関数を追加します。

static void f(int i, char j){
    System.out.println("int_char");
}

static void f(char i, double j){
    System.out.println("char_double");
}

static void f(int i, double j){
    System.out.println("int_double");
}

static void f(Character... i){
    System.out.println("Character_varargs");
}

結果は Character_varargs のままです。なんで?void f(int i, double j) と void f(Character... i) のみを考慮する場合、出力は int_double になります。

コンパイラがあいまいな関数に遭遇した場合、他の候補を考慮せずに varargs 関数 (存在する場合) に直接「ジャンプ」しますか?

ありがとう!

4

1 に答える 1