98

クイズで出てきたこの問題、

public class MoneyCalc {

   public void method(Object o) {
      System.out.println("Object Verion");
   }

   public void method(String s) {
      System.out.println("String Version");
   }

   public static void main(String args[]) {
      MoneyCalc question = new MoneyCalc();
      question.method(null);
   }
}

このプログラムの出力は「文字列バージョン」です。しかし、オーバーロードされたメソッドに null を渡すと文字列バージョンが選択される理由を理解できませんでした。null は何も指していない String 変数ですか?

ただし、コードを次のように変更すると、

public class MoneyCalc {

   public void method(StringBuffer sb) {
      System.out.println("StringBuffer Verion");
   }

   public void method(String s) {
      System.out.println("String Version");
   }

   public static void main(String args[]) {
      MoneyCalc question = new MoneyCalc();
      question.method(null);
   }
}

「メソッド method(StringBuffer) は MoneyCalc 型に対してあいまいです」というコンパイル エラーが発生します。

4

8 に答える 8

102

null は何も指していない String 変数ですか?

null 参照は、任意のクラス型の式に変換できます。の場合String、これで問題ありません。

String x = null;

ここStringでオーバーロードが選択されるのは、Java コンパイラがJLS のセクション 15.12.2.5に従って最も具体的なオーバーロードを選択するためです。特に:

非公式の直観は、最初のメソッドによって処理された呼び出しが、コンパイル時の型エラーなしで別のメソッドに渡される場合、あるメソッドが別のメソッドよりも具体的であるということです。

2番目のケースでは、両方の方法が引き続き適用可能ですが、どちらStringStringBuffer他の方法よりも具体的ではないため、どちらの方法も他の方法よりも具体的ではないため、コンパイラエラーが発生します。

于 2012-10-23T14:44:26.850 に答える
9

さらに、JLS 3.10.7では、「null」が「null 型」のリテラル値であることも宣言されています。そこで「null」という型が存在します。

その後、JLS 4.1には、変数を宣言できない null 型が存在すると記載されていますが、null リテラルでのみ使用できます。後でそれは言います:

null 参照は、常に任意の参照型への拡大参照変換を受けることができます。

コンパイラが String に拡張することを選択する理由は、Jon's answerで説明されている可能性があります。

于 2012-10-23T14:52:34.447 に答える
2

タイトルの質問に答えるには:nullは も もありStringませんObjectが、いずれかへの参照を に割り当てることができますnull

私は実際、このコードがコンパイルされることに驚いています。以前に同様のことを試しましたが、呼び出しがあいまいであるというコンパイラ エラーが発生しました。

ただし、この場合、コンパイラは食物連鎖で最も低い方法を選択しているようです。あなたを助けるために、メソッドの最も一般的でないバージョンが必要であると仮定しています。

ただし、この(一見)まったく同じシナリオでコンパイラエラーが発生した例を掘り下げることができるかどうかを確認する必要があります...]

編集: なるほど。私が作成したバージョンでは、 と を受け入れる 2 つのオーバーロードされたメソッドがStringありましたInteger。このシナリオでは、「最も具体的な」パラメーター (ObjectおよびStringのように) がないため、コードとは異なり、それらの間で選択することはできません。

とてもクールな質問です!

于 2012-10-23T14:45:59.483 に答える
2

値に a を割り当てるstringと、null値が有効になり、Java およびほとんどのプログラミング言語の順序が最も近い型に適合し、次にオブジェクトに適合します。

于 2012-10-23T14:44:45.357 に答える
0

Java コンパイラは、ほとんどの派生クラス タイプに null を割り当てます。

これを理解するための例を次に示します。

class A{

    public void methodA(){
        System.out.println("Hello methodA");
    }
}

class B extends A{
    public void methodB(){
        System.out.println("Hello methodB");
    }
}

class C{
    public void methodC(){
        System.out.println("Hello methodC");
    }
}

public class MyTest {

     public static void fun(B Obj){
         System.out.println("B Class.");
     }
     public static void fun(A Obj){
         System.out.println("A Class.");
     }

    public static void main(String[] args) {
        fun(null);
    }
}

出力: B クラス。

一方で:

public class MyTest {

     public static void fun(C Obj){
         System.out.println("B Class.");
     }
     public static void fun(A Obj){
         System.out.println("A Class.");
     }

    public static void main(String[] args) {
        fun(null);
    }
}

結果 :メソッド fun(C) は型 MyTest に対してあいまいです

このケースをよりよく理解するのに役立つことを願っています。

于 2016-11-24T11:42:50.073 に答える
0

String 型は Object 型よりも具体的です。整数型を取るメソッドをもう 1 つ追加するとします。

public void method(Integer i) {
      System.out.println("Integer Version");
   }

次に、呼び出しがあいまいであることを示すコンパイラ エラーが表示されます。今と同じように、同じ優先順位を持つ 2 つの等しく固有のメソッドがあります。

于 2015-10-02T11:17:25.437 に答える
-1

どちらとも言えません。NULL は値ではなく状態です。詳細については、このリンクを参照してください (記事は SQL に適用されますが、質問にも役立つと思います)。

于 2012-10-23T14:46:55.740 に答える