1. ホーム
  2. java

[解決済み] JavaでNULL文字列を連結する【重複】について

2022-04-21 10:26:11

質問

なぜ以下のようになるのでしょうか? 私が期待するのは NullPointerException をスローします。

String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"

解決方法は?

なぜ をしなければならない。 動作するのか?

<ストライク JLS 5, 15.18.1.1項 JLS 8 §15.18.1 "文字列の連結演算子 +" につながる。 JLS 8, §5.1.11 "文字列の変換" は、この操作が失敗せずに成功することが必要です。

...あとは参照値のみを考慮すればよい。 参照がNULLの場合、文字列 "null"に変換されます。 (4つのASCII文字n, u, l, l)です。それ以外の場合は、あたかも参照されたオブジェクトのtoStringメソッドを引数なしで呼び出したかのように変換されます。ただし、toStringメソッドを呼び出した結果がNULLだった場合は、代わりに文字列 "null"が使用されます。

どのように は、どのように機能するのでしょうか?

バイトコードを見てみよう! コンパイラはあなたのコードを

String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"

で、代わりにこう書いたかのようにバイトコードにコンパイルします。

String s = null;
s = new StringBuilder(String.valueOf(s)).append("hello").toString();
System.out.println(s); // prints "nullhello"

(自分で javap -c )

の append メソッド。 StringBuilder はすべてnullをうまく処理します。 この場合 null が第一引数です。 String.valueOf() が代わりに呼び出される。StringBuilder には任意の参照型を受け取るコンストラクタがないからである。

もし仮に s = "hello" + s の代わりに、同等のコードは次のようになります。

s = new StringBuilder("hello").append(s).toString();

ここで、この場合、appendメソッドはnullと その後 に委ねる。 String.valueOf() .

文字列の連結は、どの最適化を行うかをコンパイラが決定できる稀な場所の1つです。そのため、正確な等価値はコンパイラによって異なる可能性があります。この最適化は JLS 15.18.1.2項 :

Javaコンパイラは、文字列の連結を繰り返す際のパフォーマンスを上げるために、StringBufferクラスや同様の手法を用いて、式の評価によって生成される中間Stringオブジェクトの数を減らすことがあります。

上記の "等価コード" を決定するために使用したコンパイラは、Eclipse のコンパイラです。 ecj .