web-dev-qa-db-ja.com

Javaでのヌル文字列の連結

なぜ次のように機能しますか? NullPointerExceptionがスローされることを期待します。

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

なぜする必要があるのか​​

JLS 5、セクション15.18.1.1JLS 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を使用して自分で行うことができます

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

代わりにs = "hello" + sを実行した場合、同等のコードは次のようになります。

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

この場合、appendメソッドはnullを受け取り、thenString.valueOf()にそれを委任します。

注:文字列の連結は、実際には、コンパイラが実行する最適化を決定するまれな場所の1つです。そのため、「完全に同等の」コードはコンパイラごとに異なる場合があります。この最適化は JLS、セクション15.18.1.2 で許可されています:

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

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

177
Mark Peters

Java言語仕様のセクション 5.4 および 15.18 を参照してください。

引数の1つが文字列の場合、文字列変換はバイナリ+演算子のオペランドにのみ適用されます。この単一の特殊なケースでは、+への他の引数は文字列に変換され、2つの文字列の連結である新しい文字列は+の結果です。文字列変換は、文字列連結+演算子の説明内で詳細に指定されます。

そして

1つのオペランド式のみがString型の場合、実行時に文字列を生成するために、他のオペランドで文字列変換が実行されます。結果は、2つのオペランド文字列の連結であるStringオブジェクト(式がコンパイル時の定数式(§15.28)でない限り、新しく作成された)への参照です。新しく作成された文字列では、左側のオペランドの文字が右側のオペランドの文字に先行します。 String型のオペランドがnullの場合、そのオペランドの代わりに文字列「null」が使用されます。

24
Jonathon Faust

2行目は次のコードに変換されます。

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

Appendメソッドは、null引数を処理できます。

11
Roland Illig

「null」を使用していないため、例外は発生しません。 NullPointerが必要な場合は、

String s = null;
s = s.toString() + "hello";

そして、あなたがやりたいことは

String s = "";
s = s + "hello";
10
krico

これは、Java AP​​Iの String.valueOf(Object) メソッドで指定された動作です。連結を行う場合、valueOfを使用してString表現を取得します。オブジェクトがnullの場合は特別なケースがあり、その場合は文字列"null"が使用されます。

public static String valueOf(Object obj)

Object引数の文字列表現を返します。

パラメータ:obj-オブジェクト。

返却値:

引数がnullの場合、「null」に等しい文字列。それ以外の場合、obj.toString()の値が返されます。

7
wkl