"null" 被视为字符串吗?

6
String s = null;
s = s + "hai";
System.out.println(s);

输出:

nullhai

我本以为这会让我遇到NPE异常。

那么,为什么在使用+(拼接)时不会抛出NPE异常,而在使用.时会抛出NPE异常呢?


1
语言规范定义了它的工作方式,请参见:http://docstore.mik.ua/orelly/java/fclass/ch02_03.htm - Matthew Watson
3个回答

4

针对代码中的 s = s + "hai";,实际上会调用内部方法 String.valueOf(null)。该方法将把 null 转换成字符串 "null"

字节码:

public static void main(java.lang.String[])   throws java.lang.Exception;
    0:   aconst_null
  //some code
   10:  invokestatic    #27; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;// check this line
// some other code
       27:  return

3
不,它不会。编译器将字符串连接替换为使用StringBuilder操作,这不会导致空指针异常。编译器在后端完成所有这些操作,节省了我们编写样板代码的时间。实际上,并不存在所谓的字符串连接,因为字符串是不可变的。
反编译代码:
    String s = null; 
    s = (new StringBuilder(String.valueOf(s))).append("hai").toString(); 
    System.out.println(s);

因此,对于你的问题的答案。

  1. 编译器在内部使用StringBuilderString.valueOf操作来改变+连接操作。因此,编译器确保处理了null情况
  2. String实例上使用.运算符时,您将调用在String实例中定义的方法,例如String.concat(String str),如果您的String实例为null,则会出现NullPointerException

1
我认为你应该更加强调String.valueOf()被内部调用。如果没有valueOf(),你将会得到一个NPE。 :) - TheLostMind
@TheLostMind 我认为我已经解答了使用+运算符进行字符串拼接的工作原理,但是String.valueOf也是很重要的。 - Kumar Abhinav
哇,那我把 s +=“一些文本\n”;(10行)转换成字符串构建器是没有用的吗?编译器已经这样做了,以防止初始化太多字符串? - CausingUnderflowsEverywhere

1

NullPointerException只会在您尝试在引用为null时调用方法(或尝试访问其字段;或手动抛出NullPointerException)时抛出。

在您的情况下,这种情况不会发生,因为您的null引用将被转换为"null" String,不会在s本地变量上调用任何方法。

例如:

String s = null;
boolean isNull = s == null; // This is ok, just testing the value of s
s.toString();               // NPE, s is null

此外,请注意,即使变量为null,也可以访问静态字段:
s.valueOf(12);             // THIS IS ALSO OK, valueOf(int) is static
// It is equivalent to:
String.valueOf(12);

这很有趣!!对于静态方法,引用会指向类吗?我的意思是,s.XXX等同于String.XX吗? - Vinay Veluri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接