36

次の動作について論理的な言語設計タイプの説明はありますか(Java 7と私は以前のエディションも疑っています):

    Object  a = null;
    String as = String.valueOf(a);              // as is assigned "null"
    System.out.println(as+":"+as.length());     // prints: "null:4"
    System.out.println ( String.valueOf(null)); // NPE
4

3 に答える 3

43

In statement System.out.println(String.valueOf(null)); there is a call of method public static String valueOf(char data[]), which source code is as follows:

public static String valueOf(char data[]) {
  return new String(data);
}

That is why you get NPE

On the other hand, in statement Object a = null; String as = String.valueOf(a); there is a calls of method public static String valueOf(Object obj), which source code is as follows:

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

That is why you get "null" instead of NPE


A bit of theory from Java Language Specification: 15.12.2.5 Choosing the Most Specific Method

If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.

A char[] is of type Object, but not all Object are of type char[]. Type char[] is more specific than Object and as described in the Java Language Specification, the String.valueOf(char[]) overload is chosen in this case.

EDIT

It is also worth mentioning what Ian Roberts mentioned (in his comment below):

It's important to note that it's a compile error if there is no single overloading that is more specific than all the others - if there were a valueOf(String) method as well as valueOf(Object) and valueOf(char[]) then a call to the untyped String.valueOf(null) would be ambiguous

于 2013-01-02T15:16:36.020 に答える
15

The first invocation is to String#valueOf(Object), the second is to String#valueOf(char[])

The overloaded method is chosen according to the argument's static type, this is why the first works and the seconds get an NPE.

If you invoke System.out.println ( String.valueOf((Object)null)); it will work

于 2013-01-02T15:15:59.810 に答える
7

これは、Stringクラス内のこのコードが原因です。

public static String valueOf(char data[]) {
return new String(data);
}

コード(をスローするNullPointerException)は上記のメソッドを呼び出すため、dataフィールドはnullです。実際、この呼び出しはStringコンストラクターのクラスによってスローされます。

JDK 6を使用する場合、例外は次のとおりです。

java.lang.NullPointerException
    at java.lang.String.<init>(String.java:177)
    at java.lang.String.valueOf(String.java:2840)
    at org.bfs.data.SQLTexter.main(SQLTexter.java:364)

あなたのラインに関して:

System.out.println(as+":"+as.length());     // prints: "null:4"

これは、以下のメソッドが呼び出されるときに機能します。

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

明らかに、aはタイプでObjectあるため、String.valueOf(Object)メソッドが呼び出されます。

特にメソッドを呼び出したい場合はString.valueOf(Object obj)、次のようにnullを型キャストします。

System.out.println (String.valueOf((Object)null));

You're experiencing method overloading (where there are several method with the same name and method signature, but have different method parameters). In your case (where NPE occurs), the JVM determines which method to call based on the most specific static type. If the type is declared, then the most specific method is the method with the same parameter type of the declared variable, else, a most specific method rule is used by the JVM to find which method to invoke.

I hope this helps.

于 2013-01-02T15:13:47.983 に答える