在Java中,return null 是否安全, 为什么?

Java代码中return value 为null 是不是在任何情况下都可以,为什么不会throw NullPointerException?

Java语言层面:null值自身是不会引起任何问题的。它安安静静的待在某个地方(局部变量、成员字段、静态字段)不会有任何问题;它从一个地方被搬运到另一个地方也不会有任何问题(变量赋值、返回值等)。唯一会因为null值而引起NullPointerException的动作是“解引用”(dereference)——也就是通过这个引用要对其引用的对象做操作。俗话说就是所有隐含“obj.xxx”的操作中,obj为null值的情况。

在Java里,下述操作隐含对引用的解引用:

读字段(字节码 getfield):x.y,当x为null时抛NPE;

写字段(字节码 putfield):x.y = z,当x为null时抛NPE。注意:z的值是什么没关系;

读数组长度(字节码 arraylength):a.length,当a为null时抛NPE;

读数组元素(字节码 <x>aload,<x>为类型前缀):a[i],当a为null时抛NPE;

写数组元素(字节码 <x>astore,<x>为类型前缀):a[i] = x,当a为null时抛NPE。注意:x的值时什么没关系;

调用成员方法(字节码 invokevirtual、invokeinterface、invokespecial):obj.foo(x, y, z),当obj为null时抛NPE。注意:参数的值是什么没关系;

增强for循环(也叫foreach循环):

对数组时(实际隐含a.length操作):for (E e : a) { ... } , 当a为null时抛NPE;

对Iterable时(实际隐含对Iterable.iterator()的调用):for (E e : es) { ... } ,当es为null时抛NPE;

自动拆箱(实际隐含 <XXX>.<xxx>Value() 的调用,<XXX>为包装类型名,<xxx>为对应的原始类型名): (int) integerObj,当integerObj为null时抛NPE;

对String做switch(实际隐含的操作包含对String.hashCode()的调用):switch (s) { case "abc": ... } ,当s为null时抛NPE;

创建内部类对象实例(字节码 new,但这里特指创建内部类实例的情况):outer.new Inner(x, y, z),当outer为null时抛NPE;

抛异常(字节码 athrow):throw obj,当obj(throw表达式的参数)为null时抛NPE;

用synchronized关键字给对象加锁(字节码 monitorenter / monitorexit):synchronized (obj) { ... },当obj为null时抛NPE。

Java语言里所有其它语法结构都不会因为null值而隐含抛NPE的语义。当然,用户可以在自己需要的地方显式检查null值然后自己抛出NPE,就像:


  1. java.util.Objects.requireNonNull(Object)
  2. /**
  3. * Checks that the specified object reference is not {@code null}. This
  4. * method is designed primarily for doing parameter validation in methods
  5. * and constructors, as demonstrated below:
  6. * <blockquote><pre>
  7. * public Foo(Bar bar) {
  8. * this.bar = Objects.requireNonNull(bar);
  9. * }
  10. * </pre></blockquote>
  11. *
  12. * @param obj the object reference to check for nullity
  13. * @param <T> the type of the reference
  14. * @return {@code obj} if not {@code null}
  15. * @throws NullPointerException if {@code obj} is {@code null}
  16. */
  17. public static <T> T requireNonNull(T obj) {
  18. if (obj == null)
  19. throw new NullPointerException();
  20. return obj;
  21. }

自己主动throw new NullPointerException()这种情况JVM管不着,用户代码主动指定的,用户想怎么搞就怎么搞。

趣味题:在Java语言里,只使用Java语言及标准库的功能而不依赖第三方库,检查一个引用obj是否为null并在null时抛NPE的代码是什么?

答案:obj.getClass()。这是因为getClass()是java.lang.Object类上的方法,因而无论什么引用类型都可以使用。这在Java源码层面和在Java字节码层面上都是最短的。

当然这是个很邪恶的歪招,然而在OpenJDK的标准库内部实现中并不少见。大家…还是用Objects.requireNonNull()就好了.

return null主要多了一个麻烦,凡是调用它的地方,都要想一想,是不是要判断if (xxx == null),这样代码不够优雅。

语言层面上讲,返回null没有任何问题,大家都赞同。

工程实践中,返回null是否就是个不好的习惯?我倒不这么认为。我的观点是,所有的方法调用,无论是自己工程的内部类方法还是第三方包中的方法,除非对方在Java Doc中显式的说明了不会返回空,其它情况都应该怀疑有返回空指针的可能性。多一个判断并没有什么不好,还能大大增加代码的健壮性。在另一方面,方法的编写者也应该仔细的维护Java Doc,如果会返回空指针,那应该说明原因和语义,让调用者有章可依。

原文地址:https://www.cnblogs.com/jpfss/p/9366182.html

时间: 2024-08-05 00:29:04

在Java中,return null 是否安全, 为什么?的相关文章

java中的null注意事件总结

对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰.连Java的发明者都承认这是他的一项巨大失误.Java为什么要保留null呢?null出现有一段时间了,并且我认为Java发明者知道null与它解决的问题相比带来了更多的麻烦,但是null仍然陪伴着Java. 我越发感到惊奇,因为java的设计原理是为了简化事情,那就是为什么没有浪费时间在指针.操作符重载.多继承实现的原因,null却与此正好相反.好吧,我真的不知道这个问题的答案,我知道的是不管null被Ja

转!!Java中关于Null的9个解释(Java Null详解)

对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰.连Java的发明者都承认这是他的一项巨大失误.Java为什么要保留null呢?null出现有一段时间了,并且我认为Java发明者知道null与它解决的问题相比带来了更多的麻烦,但是null仍然陪伴着Java. 我越发感到惊奇,因为java的设计原理是为了简化事情,那就是为什么没有浪费时间在指针.操作符重载.多继承实现的原因,null却与此正好相反.好吧,我真的不知道这个问题的答案,我知道的是不管null被Ja

Java中的null关键字

先看一段代码 public class NULL { public static void Test(){ System.out.println("这是Test()的输出!!"); } public static void main(String[] args) { ((NULL)null).Test(); } } 上面的代码有没有错误? 答案是没有!! 编译运行 输出结果: 这是Test()的输出!! 这是因为Java中,null是一个关键字,用来标识一个不确定的对象.因此可以将nu

Java中的NULL

对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰.连Java的发明者都承认这是他的一项巨大失误.Java为什么要保留null呢?null出现有一段时间了,并且我认为Java发明者知道null与它解决的问题相比带来了更多的麻烦,但是null仍然陪伴着Java. 我越发感到惊奇,因为java的设计原理是为了简化事情,那就是为什么没有浪费时间在指针.操作符重载.多继承实现的原因,null却与此正好相反.好吧,我真的不知道这个问题的答案,我知道的是不管null被Ja

Java中的null对象也可以访问static成员变量和方法

声明:本博客为原创博客,未经允许,不得转载!小伙伴们如果是在别的地方看到的话,建议还是来csdn上看吧(链接为 http://blog.csdn.net/bettarwang/article/details/26515271),看代码和提问.讨论都更方便. 一般来说,一个类的对象要在实例化之后才可以访问类中的成员变量和方法.如果它还是null,通常意义上我们就认为它不能访问类中的成员.实际上确实不提倡这样,而且null对象确实不能访问实例成员(变量和方法),否则会引发NULLPointerExc

Java中有关Null的9件事

对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰.连Java的发明者都承认这是他的一项巨大失误.Java为什么要保留null呢?null出现有一段时间了,并且我认为Java发明者知道null与它解决的问题相比带来了更多的麻烦,但是null仍然陪伴着Java. 我越发感到惊奇,因为java的设计原理是为了简化事情,那就是为什么没有浪费时间在指针.操作符重载.多继承实现的原因,null却与此正好相反.好吧,我真的不知道这个问题的答案,我知道的是不管null被Ja

Java中有关 null 的9件事

Java中有关 null 的9件事 对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰. 连Java的发明者都承认这是他的一项巨大失误.Java为什么要保留null呢?null出现有一段时间了,并且我认为Java发明者知道null与它解决的问题相比带来了更多的麻烦,但是null仍然陪伴着Java. 我越发感到惊奇,因为java的设计原理是为了简化事情,那就是为什么没有浪费时间在指针.操作符重载.多继承实现的原因,null却与此正好相反.好吧,我真的不知道这个问

经典的java中return和finally问题!

经典的java中return和finally问题! 标签: 杂谈 分类: java学习 前一段时间 参加公司的笔试问了这个问题,回来一查才知道当时自己做错了,百思不得其解,上网查到下面的程序,但是运行后发现了错误,我修改后放在了我的blog 上面,希望和大家分享. 代码如下: public class Test { public static void main(String[] args) { System.out.print(tt()); } public static int tt() {

Java中有关Null的9件事(转)

对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰.连Java的发明者都承认这是他的一项巨大失误.Java为什么要保留null呢?null出现有一段时间了,并且我认为Java发明者知道null与它解决的问题相比带来了更多的麻烦,但是null仍然陪伴着Java. 我越发感到惊奇,因为java的设计原理是为了简化事情,那就是为什么没有浪费时间在指针.操作符重载.多继承实现的原因,null却与此正好相反.好吧,我真的不知道这个问题的答案,我知道的是不管null被Ja

java中的null类型---有关null的9件事

摘自 https://blog.csdn.net/qq_25077777/article/details/80174763 今天听到一个问题,java中的null类型,null竟然是一种类型 java语言中有两种类型,一种是基本类型,还有一种是引用类型.还有一个特殊的null类型即表达式null的类型,它没有名字. 因为null类型没有名字,所以不可能声明为null类型的变量或者转换为null类型. null引用是null类型表达式唯一可能的值. null引用可以转换为任意引用类型. 实际上,程