Java中字符串和整数的空值

时间:2013-01-26 16:24:31

标签: java string nullpointerexception addition autoboxing

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");       
        }
    }

}

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

6 个答案:

答案 0 :(得分:60)

您的代码使用了两个不同的additive operators。前三行使用string concatenation,而最后一行使用numeric addition

字符串连接是well-defined to turn null into "null"

  
      
  • 如果引用为null,则会将其转换为字符串"null"(四个ASCII字符nul,{{1} })。
  •   

因此没有NPE。

将两个l个对象添加到一起需要它们为unboxed。这会导致Integer引用被取消引用,从而导致NPE:

  
      
  • 如果null为空,则取消装箱转化将引发r
  •   

答案 1 :(得分:17)

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

StringBuilder tmp = new StringBuilder();
tmp.append(s);
tmp.append(i);
System.out.println(tmp);

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

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

答案 2 :(得分:5)

+的任何内容的连接(String运算符)都会产生String。每个操作数首先转换为字符串(使用toString()或使用值"null"),然后连接。

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

答案 3 :(得分:1)

似乎是自动拆箱的情况。如果您有两个Integer firstsecond,则其添加结果将为first.intValue() + second.intValue()。由于它们都是null,因此导致NPE。

答案 4 :(得分:0)

查看程序的字节码。您会注意到您的null对象作为参数传递给PrintStream.print()方法。 print()方法的源代码使用String.valueOf(),如下所示:

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

答案 5 :(得分:0)

应该注意的是,从输出中可以明显看出这个问题的答案:

C:\Temp>java Test
nullnull
nullnull
nullnull
NullPointerException