5 ответов:
почему должны он работает?
The
JLS 5, раздел 15.18.1.1JLS 8 § 15.18.1 " оператор конкатенации строк+", ведущей к JLS 8, § 5.1.11 "преобразование строк", требует, чтобы эта операция прошла успешно без сбоев:...Теперь нужно учитывать только опорные значения. если ссылка имеет значение null, она преобразуется в строку "null" (четыре 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все обрабатывают нуль просто отлично. В данном случае потому чтоnull- первый аргументString.valueOf()вызывается вместо этого, так как StringBuilder не имеет конструктора, который принимает любой произвольный ссылочный тип.если бы ты это сделал
s = "hello" + sвместо эквивалентный код будет такой:s = new StringBuilder("hello").append(s).toString();, где в это случае метод append принимает значение null и затем делегаты его
String.valueOf().Примечание: конкатенация строк на самом деле является одним из редких мест, где компилятор решает, какую оптимизацию(ы) выполнять. Таким образом," точный эквивалент " кода может отличаться от компилятора к компилятору. Эта оптимизация разрешена JLS, раздел 15.18.1.2:
для увеличения производительности повторяющейся строки конкатенация, компилятор Java может использовать класс StringBuffer или аналогичный метод для уменьшения числа промежуточных строковых объектов, которые создаются путем вычисления выражения.
компилятор, который я использовал для определения "эквивалентного кода" выше, был компилятором Eclipse, ecj.
раздел 5.4 и 15.18 спецификации языка Java:
преобразование строк применяется только к операнда бинарного оператора+, когда одним из аргументов является строка. В это один особый случай, другой аргумент + преобразуется в Строка, и новая строка, которая является конкатенация двух строк результат работы +. Преобразование строк подробно указана в описание строка оператор конкатенации.
и
Если только одно выражение операнда имеет введите строку, затем преобразование строки выполняется на другом операнде, чтобы создайте строку во время выполнения. Этот результатом является ссылка на строку объект (вновь созданный, если выражение является константой времени компиляции выражение (§15.28)) то есть конкатенация двух операндов веревка. Персонажи фильма левый операнд предшествует символы правого операнда во вновь созданной строке. Если операнд типа String имеет значение null, то строка "null" используется вместо этот операнд.
вторая строка преобразуется в следующий код:
s = (new StringBuilder()).append((String)null).append("hello").toString();методы добавления могут обрабатывать
nullаргументов.
вы не используете "null", и поэтому вы не получаете исключение. Если вы хотите NullPointer, просто сделайте
String s = null; s = s.toString() + "hello";и я думаю, что вы хотите сделать, это:
String s = ""; s = s + "hello";
это поведение, указанное в API Java
String.valueOf(Object)метод. Когда вы делаете конкатенацию,valueOfдля полученияStringпредставление. Существует особый случай, если объектnullв этом случае строку есть.
public static String valueOf(Object obj)возвращает строковое представление аргумента объект.
параметры: obj - объект.
возвращает:
если аргумент-null, затем строка, равная "null"; в противном случае значение obj.toString() возвращается.
Comments