почему "abc" + нулевые результаты abcnull - PullRequest
1 голос
/ 19 января 2011

почему "abc" + null результаты abcnull

String s1 = "abc";
String s2 = null; 
String s3 = s1+ s2;

System.out.println(s3);

Результат: abcnull

Ответы [ 9 ]

7 голосов
/ 19 января 2011

Поскольку Java создаст StringBuilder для добавления s1 или "abc", к s2 или null.

Согласно спецификации для StringBuilder.append (String) -

If str is null, then the four characters "null" are appended

Так что получается так же, как "abc" + "null"

Давайте рассмотрим пример кода (я поместил его в метод):

 public static void main(String[] args)
 {
  String s1 = "abc";
  String s2 = null; 
  String s3 = s1+ s2;
  System.out.println(s3);
 }

Если мы посмотрим на байт-код (полученный с помощью вызова javap -c):

public static void main(java.lang.String[]);
  Code:
   0:   ldc #2; //String abc
   2:   astore_1
   3:   aconst_null
   4:   astore_2
   5:   new #3; //class java/lang/StringBuilder
   8:   dup
   9:   invokespecial   #4; //Method java/lang/StringBuilder."<init>":()V
   12:  aload_1
   13:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   16:  aload_2
   17:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   20:  invokevirtual   #6; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   23:  astore_3
   24:  getstatic   #7; //Field java/lang/System.out:Ljava/io/PrintStream;
   27:  aload_3
   28:  invokevirtual   #8; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   31:  return

Java создает StringBuilder и добавляет значения, как String s, s1 и s2.

Так что вам следует быть осторожным, если вы ожидали исключение NullPointerException, потому что конкатенация в Java обойдет проблему.

Примечание: Как указал Джон Скит , это в конечном итоге всего лишь 1031 * реализация деталей - это спецификация Java, которая гарантирует, что нуль при преобразовании в String превращается в "ноль". Однако этот байт-код, по крайней мере, показывает, что на самом деле происходит за кулисами.

4 голосов
/ 19 января 2011

Это именно то значение, которое гарантируется спецификацией языка.Из раздела 15.8.1.1 JLS , в котором говорится о преобразованиях строк, используемых для конкатенации строк:

Теперь необходимо учитывать только ссылочные значения.Если ссылка имеет значение null, она преобразуется в строку «null» (четыре символа ASCII n, u, l, l).В противном случае преобразование выполняется как бы путем вызова метода toString ссылочного объекта без аргументов;но если результат вызова метода toString равен нулю, тогда вместо него используется строка «null».

(Вам может быть интересно услышать, что .NET использует другой подход, преобразуя нулевую ссылкув пустой строке. У каждого подхода есть свои плюсы и минусы - я считаю, что подход Java более полезен для создания строки для отладки, но подход .NET более полезен при построении строки, отображаемой пользователю или сохраняемой в файл данных.и др.)

1 голос
/ 19 января 2011

Так работает конкатенация строк.

Если вам не нужно объединять слово "null", вы можете сделать:

String s3 = (s1==null?"":s1) + (s2==null?"":s2);
0 голосов
/ 19 января 2011

Давайте скомпилируем ваш код и посмотрим на байт-код:

   // -- Initialization of s1
   5:   ldc             #2; //String abc
   7:   putfield        #3; //Field s1
   // ...

   // -- Initialization of s2
   11:  aconst_null
   12:  putfield        #4; //Field s2
   // ...

   // -- Initialization of s3
   //    create a StringBuilder
   16:  new             #5; //class StringBuilder
   19:  dup
   20:  invokespecial   #6; //Method StringBuilder."<init>"
   // Load s1
   23:  aload_0
   24:  getfield        #3; //Field s1
   // Call StringBuilder.append(String)
   27:  invokevirtual   #7; //Method StringBuilder.append(String)
   30:  aload_0
   // Load s2
   31:  getfield        #4; //Field s2
   // Call StringBuilder.append(String)
   34:  invokevirtual   #7; //Method StringBuilder.append(String)
   // Get content of StringBuilder
   37:  invokevirtual   #8; //Method StringBuilder.toString()
   // Store in s3
   40:  putfield        #9; //Field s3

Так как же получается "null" в результате?Что ж, это описано в документации StringBuilder.append(String):

Символы аргумента String добавляются по порядку, увеличивая длину этой последовательности на длину аргумента.Если str имеет значение null, тогда добавляются четыре символа «null».

Как отмечает Джон Скит, все это соответствует Спецификации языка Java.

0 голосов
/ 19 января 2011

это потому, что любая вещь, которую вы добавляете в строку, по умолчанию преобразует ее в строку. и даже если вы попытаетесь добавить число в строку, оно будет преобразовано в строку. пример: "ABC" + 123 = "абв123" существует синтаксис concat, который добавляет строку к строке, а не что-либо еще. пример : если вы печатаете "А" .concat (нуль) тогда это покажет java.lang.NullPointerException at java.lang.String.concat (неизвестный источник) но если ты введешь "А" .concat ( "нулевой") вывод будет "abcnull".

0 голосов
/ 19 января 2011

Так работает Java-конкатенация. Он обрабатывает нулевые объекты как "нулевые".

Пожалуйста, смотрите эту ссылку

0 голосов
/ 19 января 2011

Конкатенация строк в Java выполняет автоматическое преобразование. Нулевая строка будет преобразована в строку 'null'. Для справки см. Например эта страница :

Нулевой операнд преобразуется в строковый литерал "null".

Чтобы избежать этого, вам следует самостоятельно проверить, является ли одна строка нулевой.

0 голосов
/ 19 января 2011
String s = "a" + null;

компилятор понимает его как

String s = "a" + String.valueOf(null)

так

String s = "a" + String.valueOf(null)/* null*/  = "anull";

В вашем примере

String s3 = String.valueOf(s1) + String.valueOf(s2);
s3 = "abc" + "null" // absnull
0 голосов
/ 19 января 2011

Я не знаю Java, но, судя по всему, кажется, что вы используете s2 в качестве объекта String, который затем превращает null в "null". Пожалуйста, поправьте меня, если я ошибаюсь.

...