Java 中 null 的行为

Behaviour of null in Java

这可能看起来与 SO 上的其他问题重复。但是,我想知道 Java 对待 null 的方式。

例如:

public class Work {
    String x = null;
    String y;
    Integer z;

    public static void main(String arg[]) {
        Work w = new Work();
        w.x = w.x + w.y; // work Line 1
        w.x = w.x + w.y + w.z; // work Line 2
        w.z = w.z + w.z; // NullPointerException Line 3
        System.out.println(w.x.charAt(4));
    }
}

注释 Line 3 打印 n 而取消注释抛出 NullPointerException。如果我对 Line 1Line 2 没记错的话,它被隐式类型转换为 String。但是, Line 3 发生了什么?

开始拆箱。整数没有 + 运算符。它必须拆箱为 int(原始)。

String在Java有很多特殊津贴,不管是好是坏。规范规定 null 在转换为字符串时会转换为字符串 "null",例如通过字符串连接(在其他操作数上隐式调用 toString())。因此,根据语言规范的说法,将 null 添加到字符串中是可行的。

基于此,您的前两行将导致

w.x = "null" + "null";
w.x = "nullnull" + "null" + "null";

在第 3 行中,您会看到不同的现象,在本例中是自动装箱和拆箱。为了简化基本类型和它们各自的包装器 类 之间的脱节,您可以将算术运算符应用于包装器 类,这会提示对它们的值进行拆箱、操作,并再次装箱结果。这就是 NullReferenceException 发生的地方,因为 w.z 仍然是 null,因此无法拆箱。本质上:

w.z = w.z + w.z

被编译器变成:

w.z = Integer.valueOf(w.z.intValue() + w.z.intValue());

而对 intValue() 的调用失败了,因为 w.z 在这里是 null

在 Java 5 之前,如果您想对 Integer 个对象进行计算,这是您必须自己编写的内容。

在java中,参考默认值为null。当您声明 z 但未初始化时,它将采用默认值 null 因为 z 是一个引用变量。因此你得到了 NullPointerException.

有 2 种方法可以避免 NullPointerException

  1. 初始化z.

    public class Work {
        String x = null;
        String y;
        Integer z = 0;   
    
        public static void main(String arg[]) {
            Work w = new Work();
            w.x = w.x + w.y; // work Line 1
            w.x = w.x + w.y + w.z; // work Line 2
            w.z = w.z + w.z; // work Line 3 
            System.out.println(w.x.charAt(4));
        }
    }
    
  2. 重新分配时使用 valueOf(int i)。

    w.z = (null == w.z) ? 0 : Integer.valueOf(w.z.intValue() + w.z.intValue());