重複の可能性:
Javaでのnull文字列の連結
コードスニペットの下を見つけてください
String str = null;
str = str + "hi";
System.out.println(str)
上記のコードの出力はですnullhi
。
出力はそうなると思っていたhi
ので、出力にちょっと驚いて、その背後にある理由を見つけることができませんでした。
誰か説明してもらえますか?
重複の可能性:
Javaでのnull文字列の連結
コードスニペットの下を見つけてください
String str = null;
str = str + "hi";
System.out.println(str)
上記のコードの出力はですnullhi
。
出力はそうなると思っていたhi
ので、出力にちょっと驚いて、その背後にある理由を見つけることができませんでした。
誰か説明してもらえますか?
これはappend
メソッドだからです。+
いずれかStringBuilder
またはStringBuffer
追加操作として変換されます。
public AbstractStringBuilder append(String str) {
if (str == null) str = "null";
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
以下は、プログラム用に生成されたバイトコードです
0 aconst_null
1 astore_1 [str]
2 new java.lang.StringBuilder [16]
5 dup
6 aload_1 [str]
7 invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [18]
10 invokespecial java.lang.StringBuilder(java.lang.String) [24]
13 ldc <String "hi"> [27]
15 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [29]
18 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [33]
21 astore_1 [str]
22 getstatic java.lang.System.out : java.io.PrintStream [37]
25 aload_1 [str]
26 invokevirtual java.io.PrintStream.println(java.lang.String) : void [43]
29 return
したがって、コードは実際にに変換されappend(null)
、そのappend("hi")
ような出力が得られるのはそのためです。
また、それは明確に文書化されています15.18.1. String Concatenation Operator +
実装では、中間のStringオブジェクトの作成と破棄を回避するために、変換と連結を1つのステップで実行することを選択できます。繰り返される文字列連結のパフォーマンスを向上させるために、JavaコンパイラはStringBufferクラスまたは同様の手法を使用して、式の評価によって作成される中間Stringオブジェクトの数を減らすことができます。
JLSから。
http://docs.oracle.com/javase/specs/jls/se7/html/index.html
§15.18.1。文字列連結演算子+(参照)
1つのオペランド式のみがString型である場合、実行時に文字列を生成するために、もう1つのオペランドで文字列変換(§5.1.11)が実行されます。
§5.1.11。文字列変換(参照)
参照がnullの場合、文字列「null」(4つのASCII文字n、u、l、l)に変換されます。
null
javaでnull参照を出力しようとした場合に出力される値です。
すべての文字列ではない値を連結すると、変換されない値は、のように変換されString.valueOf
ます。 String.valueOf(null)
文字列"null"
です。
これは、Javaの作成者が早い段階で下した決定でした。文字列に連結されたnull値は、として出力されnull
ます。ログメッセージを出力しようとしていると想像する場合、この種の意味があります。
String personName = null;
System.out.println("Person name is: " + personName);
結果:
人名は:null
この動作は、変数が実際にはnullであることがわかっているため(たとえば、空の文字列ではなく)、デバッグ時に役立ちます。
あなたがこれを行おうとしたときに彼らは単に例外をスローすることを選択できたかもしれませんが、それはログメッセージや例外文字列を作成するようなことをしているときでさえ多くのことを壊してしまうでしょう。
また、期待どおりに実行し、null値を空の文字列として出力するようにすることもできます。これは、.NETFrameworkが行うことです。しかし、最終的には、それは彼らがやろうと決心したことではありません。
あなたが示した例では、文字列nullをhiと連結しているため、生成される出力は
nullhiです。
String str = null;
str = str + "hi";
System.out.println(str);
as str=str+"hi "//shows one string is concatenating with the other
したがって、得られる出力は正しいです。