对于 Java 程序员来说,null 一直是令人头疼的问题,经常会受到 NullPointerException 的蹂躏和壁咚。Java 的发明者也承认这是一个巨大的设计错误。
那么关于 null ,你应该知道下面这几件事情来有效的了解 null ,从而避免很多由 null 引起的错误。
- 首先,null 是 Java 中的
关键字
,像是 public、static、final。它是大小写敏感的,你不能将 null 写成 Null 或 NULL,编辑器将不能识别它们然后报错。
这个问题已经几乎不会出现,因为eclipse 和 Idea编译器已经给出了编译器提示,所以你不用考虑这个问题。
- 就像是基本类型的默认值一样,例如 int 的默认值是 0,boolean 的默认值是 false,null 是所有引用类型的默认值,Java中的任何引用变量都将null作为默认值,也就是说所有 Object 类下的引用类型默认值都是 null。这对所有的引用变量都适用。
publicclass DefaultNullValue { privatestatic Object value; public static void printValue(){ System.out.println("value = " + value); } public static void main(String[] args) { printValue(); } }
这对静态和非静态的object来说都是正确的。就像你在这里看到的这样,我将 value 定义为静态引用,还有一个静态方法,我可以在 main 函数中直接使用它。
- null 既不是对象也不是一种类型,它仅是一种特殊的值,你可以将它赋予任何类型,你可以将 null 转换为任何类型
public static void main(String[] args) { String str = null; Integer itr = null; Double dou = null; Integer integer = (Integer) null; String string = (String)null; System.out.println("integer = " + integer); System.out.println("string = " + string); }
你可以看到在编译期和运行期内,将null 转换成任何的引用类型都是可行的,并且不会抛出空指针异常
- null 只能赋值给引用变量,不能赋值给基本类型变量。
- 持有 null 的包装类在进行自动拆箱的时候,不能完成转换,会抛出空指针异常,并且 null 也不能和基本数据类型进行对比
public static void main(String[] args) { int i = 0; Integer itr = null; System.out.println(itr == i); }
- 使用了带有 null 值的引用类型变量,
instanceof
操作会返回false
public static void main(String[] args) { Integer isNull = null; // instanceof = isInstance 方法 if(isNull instanceof Integer){ System.out.println("isNull is instanceof Integer"); }else{ System.out.println("isNull is not instanceof Integer"); } }
这是 instanceof 操作符一个很重要的特性,使得对类型强制转换检查很有用
- 静态变量为 null 调用静态方法不会抛出 NullPointerException。因为静态方法使用了静态绑定(更多动态绑定和静态绑定的了解,请参考下面这篇文章 理解静态绑定与动态绑定),例如:
publicclass ComplingBinding { public static void staticMehtod(){ System.out.println("静态方法"); } public void instanceMethod(){ System.out.println("非静态方法"); } public static void main(String[] args) { ComplingBinding binding = null; binding.staticMehtod(); binding.instanceMethod(); } }
- 你应该使用 null-safe 安全的方法,java类库中有很多工具类都提供了静态方法,例如基本数据类型的包装类,Integer,Double 等。例如
publicclass NullSafeMethod { privatestatic String number; public static void main(String[] args) { String s = String.valueOf(number); String string = number.toString(); System.out.println("s = " + s); System.out.println("string = " + string); } }
number 没有赋值,所以默认为null,使用String.value(number)
静态方法没有抛出空指针异常,但是使用 toString()
却抛出了空指针异常。所以尽量使用对象的静态方法。
- 你可以使用
==
或者!=
操作来比较 null 值,但是不能使用其他算法或者逻辑操作,例如小于或者大于。跟SQL不一样,在Java中 null == null 将返回 true,如下所示:
publicclass CompareNull { privatestatic String str1; privatestatic String str2; public static void main(String[] args) { System.out.println("str1 == str2 ? " + str1 == str2); System.out.println(null == null); } }