Java中字符串和整数的空值

tan*_*nia 49 java string autoboxing nullpointerexception addition

public class Test {
    public static void main(String[] args) {

        String s = null;
        String s1 = null;
        Integer i = null;
        Integer i1 = null;

        System.out.println(s+i);
        System.out.println(i+s);
        System.out.println(s+s1);

        try {
            System.out.println(i+i1);
        } catch (NullPointerException np) {         
            System.out.print("NullPointerException");       
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

问题很简单 - 为什么我NullPointerException只收到最后一行?

NPE*_*NPE 60

您的代码使用两个不同的加法运算符.前三行使用字符串连接,而最后一行使用数字加法.

字符串连接定义明确,可以null变成"null":

  • 如果引用null,它被转换成字符串"null"(4个ASCII字符n,u,l,l).

因此没有NPE.

将两个Integer对象一起添加需要将它们取消装箱.这导致null引用被解除引用,从而导致NPE:

  • 如果r为null,则取消装箱转换会抛出一个NullPointerException

  • @TomaszNurkiewicz:我觉得有必要提出一个关于NPE的问题.:) (9认同)
  • +1引用JLS而不是潜入实现细节(参见我的回答;-)). (3认同)

Tom*_*icz 17

请注意,前三个+运算符用法涉及字符串连接.只有最后一个是实际的数字.当涉及字符串连接(涉及s变量)时,Java编译器使用一些聪明的技巧来提高性能.它取代了+运算符StringBuilder.例如,您的第一行被翻译为:

StringBuilder tmp = new StringBuilder();
tmp.append(s);
tmp.append(i);
System.out.println(tmp);
Run Code Online (Sandbox Code Playgroud)

StringBuildernull友好的所以无论你作为一个参数传递什么,它很好地用"null"字符串替换它.

最后一行的情况有所不同.在那里你引用了两个Integer对象.JVM在这里唯一能做的就是取消它们(i.intValue())并进行实际计算.拆箱null原因NullPointerException.


Bas*_*sen 5

连接结果的连接(+运算符).每个操作数首先转换为String(使用或使用该值),然后连接.StringStringtoString()"null"

但是最后一个操作Integer仅涉及s,因此之前的规则不适用.它不是连接,而是添加.但是要添加两个Integers,它会将对象转换Integer为原始值(int),如果Integer为null 则不可能.这就是为什么你得到一个NullPointerException.