3

次のコードを検討してください

public class Foo
{

  int value;
  public Foo (final String str, Object ... bug)
  {
    System.out.println ("Should work! 1");
  }

  public Foo (final String str, final int value, Object ... bug)
  {
     this.value = value;
    System.out.println ("Should work! 2");
  }

  public static void main (String[]args)
  {
    Foo f = new Foo ("Foo", 3); //Line 14
    System.out.println(f.value);
  }
}

jdk-1.6.x を使用していたとき、正常にコンパイルできました。しかし、jdk-1.7にアップグレードすると、エラーが発生します:

Foo.java:18: error: reference to Foo is ambiguous, both constructor Foo(String,Object...) in Foo and constructor Foo(String,int,Object...) in Foo match Foo f = new Foo ("Foo", 3); //Line 14

したがって、このエラーを回避するために、2番目のCtorを次のように変更しました

  public Foo (final String str, final Integer value, Object ... bug)
  {
     this.value = value;
    System.out.println ("Should work! 2");
  }

整数に自動ボックス化してコンパイルエラーをスキップできるようにします。

いくつかの質問:
1) それは良い習慣ですか? そうでない場合、他の方法はありますか?
2) なぜ Java 開発者は、エラーを許可するのではなく、エラーを出すという決定を下したのでしょうか?

4

2 に答える 2

4

これは設計によるものであり、Java 6 と Java 7 の間の非互換性の既知の領域です。Java 7 でオーバーロード解決アルゴリズムが修正されたためです。Java 5 および 6 では、次のコードはコンパイルされません。

class Test {
    void foo(int... i) {}
    void foo(double... d) {}

    void test() {
       foo(1,2,3);
    }
}

コンパイラは、呼び出しがあいまいであると不平を言います。しかし、これは真実ではありません。なぜなら、doubleはより一般的でintあり、したがってint、この場合は最も具体的なオプションだからです。

ただし、この修正により互換性がなくなりました (リリース ノートを参照してください。「varargs」を検索してください)。int結論は、最も具体的な方法を選択できないということですObject。どちらも他方のサブタイプではないためです。したがって、これはコンパイルされません。ただし、は のサブタイプであり、この場合は最も具体的なオプションであるため、コンパイラはそれを選択できるため、 を使用できますIntegerIntegerObject

リリースノートの関連セクション:

javacコンパイラはJDK 7より前よりも多くのコードを受け入れますが、この修正により、次の場合にソースの互換性がわずかに失われます:

class Test {
    void foo(int... i) {}
    void foo(Object... o) {}

    void test() {
       foo(1,2,3);
    }
}

このコードは JDK 6 でコンパイルされます (最も具体的な方法は ですfoo(int...))。このコードはJDK 7ではコンパイルfoo(int...)されfoo(Object...)ません。このプログラムは許可されるべきではありません (実際、そもそも許可されるべきではありませんでした)。intObjectObjectint

非互換性の性質: 行動とソース

RFE: 6199075

于 2013-04-02T17:50:48.673 に答える
1

なぜ Java 開発者はエラーを許可するのではなく、エラーを出すことにしたのでしょうか?

このエラーは、JDK 7 での var-args の認識方法が変更されたために発生します。

1)それは良い習慣ですか?そうでない場合、他の方法はありますか?

この問題を回避するために Integers を使用することはできますが、クラス Foo は元々メンバー変数として int を持っていたので、そのままにしておきます。Integer value;null を受け入れることができるようになったことに注意してください。コード内の null を確認しvalue.intValue()、値をメンバー変数に割り当てるために使用します。

キャッチされていない NPE とパフォーマンスは、オートボクシング/アンボクシングの大きな問題です。

于 2013-04-02T18:01:46.607 に答える