2011-09-10 20 views
11

printlnでは、ここでo.toString()はNPEをスローしますが、o1はスローしません。どうして?ヌル参照が "null"として印刷されるのはなぜですか

public class RefTest { 
    public static void main(String[] args) { 
     Object o = null; 
     Object o1 = null; 
     System.out.println(o.toString()); //throws NPE 
     System.out.print(o1); // does not throw NPE 
    } 
} 
+6

[すべてのドキュメント](http://download.oracle.com/javase/6/docs/api/java/io/PrintStream.html#print%28java.lang.Object%29)です。 –

答えて

25

バイトコードの表示に役立つかもしれません。あなたのクラスの次のjavap出力を見てみましょう:

> javap -classpath target\test-classes -c RefTest 

Compiled from "RefTest.java" 
public class RefTest extends java.lang.Object{ 
public RefTest(); 
    Code: 
    0: aload_0 
    1: invokespecial #8; //Method java/lang/Object."<init>":()V 
    4: return 

public static void main(java.lang.String[]); 
    Code: 
    0: aconst_null 
    1: astore_1 
    2: aconst_null 
    3: astore_2 
    4: getstatic  #17; //Field java/lang/System.out:Ljava/io/PrintStream; 
    7: aload_1 
    8: invokevirtual #23; //Method java/lang/Object.toString:()Ljava/lang/String; 
    11: invokevirtual #27; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    14: getstatic  #17; //Field java/lang/System.out:Ljava/io/PrintStream; 
    17: aload_2 
    18: invokevirtual #33; //Method java/io/PrintStream.print:(Ljava/lang/Object;)V 
    21: return 

} 

ちょうどmainメソッドを見て、あなたが興味の行を見ることができますCodeは8と33

コード8であるところですが、バイトコードを示しますあなたはo.toString()に電話します。ここでonullであるため、nullのメソッド呼び出しでは、NullPointerExceptionとなります。

コード18は、nullオブジェクトがPrintStream.print()メソッドのパラメータとして渡されることを示しています。

public void print(Object obj) { 
    write(String.valueOf(obj)); 
} 

String.valueOf()null秒でこれを行います:

public static String valueOf(Object obj) { 
    return (obj == null) ? "null" : obj.toString(); 
} 

だから、あなたがそこに見ることができるこの方法のためのソースコードを見てみると、これはNPEでない結果をする理由を紹介しますそこではnullを扱うテストであり、NPEを防ぎます。

+0

偉大な答え、ありがとう。 – abc

+1

ようこそ。私はしばしば 'javap'の出力を見てかなり洞察力があることがわかります。特に、AspectJや他のコード製織技術などのものを使用しているときに、自分のコードに行ったことを正確に見ることができます。 –

+0

コードを見る必要はありません。それはすべてドキュメントにあります。 'PrintStream :: println'は' String.valueOf'を呼び出し、明示的に "引数がnullであれば" null "に等しい文字列、それ以外の場合にはobj.toString()の値が返されます。 – njzk2

5

print(Object)は、変換のためのString.valueOf(Object)使用しているためにです(余談:print(String)が呼び出されたかのように変換println(Object)が振る舞う後、print(Object)は効果的write(int)を使用しています)。 String.valueOf(Object)o.toString()のようなNPEを投げません。ヌルパラメータには"null"を返すように定義されています。

5
System.out.println(o.toString()) 

o.toString()printlnに渡す前に、文字列に変換するためにnullオブジェクトを参照解除しようとしています。

System.out.print(o1); 

printが呼び出されるオブジェクトが進む前にヌルではないことを確認自体でprint(Object)変異体、です。

関連する問題