Java 7构造函数

use*_*315 23 java constructor

我看到了Java 7,他们介绍了这个方法Objects.requireNonNull(T obj, String message).

检查指定的对象引用是否为null,NullPointerException如果是,则抛出自定义对象引用.此方法主要用于在具有多个参数的方法和构造函数中进行参数验证.

在开始重新格式化代码之前,我会在这里要求对使用它进行一些反馈.

 public Foo(Bar bar, Baz baz) {
         /** Old one
         this.bar = bar;
         this.baz = baz;
         **/
         this.bar = Objects.requireNonNull(bar, "bar must not be null");
         this.baz = Objects.requireNonNull(baz, "baz must not be null");
   }
Run Code Online (Sandbox Code Playgroud)

在构造我的对象时直接使用它是一种更好的做法(我在考虑是否为开发人员创建库或其他东西)?

或者我应该把它留作"经典/旧的"构造函数?

Ste*_*n C 11

正如您所看到的,对于是否应抛出NPE或其他异常存在分歧1.

如果您接受NPE比替代品更合适,并且这是一种null明确不正确的情况,那么:

  • 最好早点扔掉NPE; 即在构造函数中,和
  • 最好使用自定义异常消息抛出它; 即不是nullJVM抛出NPE时发生的事情.

在这种情况下,使用Objects.requireNonNull显然是很好的做法.


您也可以使用Java断言,但是您需要判断测试是否可以关闭是好事还是坏事.您必须考虑转换早期检查的性能优势是否超过了之前未检查可能导致的问题.例如,假设您在生产中看到NPE已关闭断言...而您无法对其进行诊断.你打开断言吗?断言是否会改变代码的行为?是否会降低系统速度(由于许多其他断言检查)?引发NPE的情况是否可能再次发生?

(线程相关的错误通常是"曾经在蓝色月亮中"非常难以重现的事情.我认为你需要信息来诊断问题,无论何时发生......不仅仅是当你有断言时检查已启用.)


向后兼容性参数可能是相关的.但是,作为一般规则,您不要编写代码以在旧Java平台上运行.如果您有特定要求支持旧版Java ...那就不同了.但是如果是这种情况,那么你根本不应该对Java 7 API进行开发......所以你的编译器/ IDE应该将该Objects类标记为编译错误.

(限制自己只使用旧的API时,你不需要会让你的代码质量受到影响,并使其"过时"早.在整点新东西,使其更容易编写可靠/维护故意不使用它是...反常.想象一下,如果你限制自己使用Java 1.1 ......)


1 - FWIW,我认为NPE很好.带有消息的NPE比(比如说)更具体IllegalArgumentException,并且Java标准类库中有许多先例用于构造函数等,这些先例被记录为抛出NPE.此外,这种方法显然是以这种方式使用的.


Rav*_*yal 9

requireNonNull()抛出一个事实我感到不舒服NullPointerException.在我看来,抛出经典IllegalArgumentException使得意图更加清晰.人们也可以使用Assertions它们可以选择性地打开和关闭它们的优点.

最重要的是,如果要将代码公开为库,通常应该尽力支持最旧的JDK.

编辑:我想补充说今天选择任何一个众所周知的框架,你会发现他们的API总会抛出具有如此描述性的名称的异常,你几乎立刻就会知道什么是错的.

举个例子,当Spring容器发现@Required托管bean上的属性无法注入时会发生什么,并且仍然存在NULL.您当然不会获得NullPointerException尽可能具有描述性的错误消息.

你得到一个BeanCreationExceptionBeanInitializationException有关成员变量仍提供进一步的信息,null像一个有足够的描述错误消息:属性"中心"所需的豆"圆圈".

  • @Ravi - 许多标准集合类在使用`null`参数调用时生成NPE,许多其他标准类也是如此.这会让你"不那么自信"吗?当然,有缺陷的代码通常会产生NPE,但是进行反向推理是不合逻辑的......特别是如果你*文件*可以预期NPE的情况.如果有人认为NPE意味着你的代码有问题,那么他们就是白痴. (2认同)