方法#3:很聪明,但除非这个成语被广泛采用,否则我更喜欢更清晰,更详细的方法,而不是保存几个字符。我是一个“一次写,读很多”的程序员。arg.getClass();
其他方法是自我记录:您可以使用一条日志消息来阐明发生了什么 - 此日志消息在读取代码时以及在运行时使用。就目前而言,它不是自我记录的。您可以使用注释至少向代码的审阅者澄清:arg.getClass()
arg.getClass(); // null check
但是,您仍然没有机会像使用其他方法那样将特定消息放入运行时中。
方法 #1 与 #2(空检查+NPE/IAE 与断言):我尝试遵循这样的准则:
http://data.opengeo.org/GEOT-290810-1755-708.pdf
使用断言
检查私有方法上的参数
assert param > 0;
使用空值检查 + 非法参数异常
检查公共方法上的参数
if (param == null) throw new IllegalArgumentException("param cannot be null");
在需要时使用空检查 + 空值指针异常
if (getChild() == null) throw new NullPointerException("node must have children");
但是,由于这个问题可能是关于最有效地捕获潜在问题,那么我必须提到我的首选处理方法是使用静态分析,例如类型注释(例如)a la JSR-305。我最喜欢的检查工具是:null
null
@NonNull
Checker 框架:
Java https://checkerframework.org/manual/#checker-guarantees 的
自定义可插拔类型
如果这是我的项目(例如,不是具有公共API的库),并且如果我可以在整个过程中使用Checker框架:
另一个好处是,该工具允许我将注释放在注释中(例如'/@Nullable/),因此我的库代码可以与类型注释项目和非类型注释项目兼容(不是说我有任何这些项目)。
如果链接再次失效,以下是GeoTools开发人员指南中的部分:
http://data.opengeo.org/GEOT-290810-1755-708.pdf
5.1.7 使用断言、非法论证异常和 NPE
几年来,Java语言已经提供了一个 assert 关键字。此关键字可用于执行仅调试检查。虽然此工具有多种用途,但常见的用途是检查私有(非公共)方法上的方法参数。其他用途是后置条件和不变量。
参考:使用断言进行编程
前提条件(如私有方法中的参数检查)通常是断言的简单目标。后置条件和不变量有时不那么直截了当,但更有价值,因为非平凡条件有更多的风险被打破。
-
示例 1:在引用模块中进行地图投影后,断言将执行反向地图投影,并使用原始点(后置条件)检查结果。
-
示例 2:在 DirectPosition.equals(Object) 实现中,如果结果为 true,则断言可确保 hashCode() 与 Object 协定的要求相同。
使用 Assert 检查私有方法上的参数
private double scale( int scaleDenominator ){
assert scaleDenominator > 0;
return 1 / (double) scaleDenominator;
}
您可以使用以下命令行参数启用断言:
java -ea MyApp
您可以使用以下命令行参数仅打开 GeoTools 断言:
java -ea:org.geotools MyApp
您可以禁用特定包的断言,如下所示:
java -ea:org.geotools -da:org.geotools.referencing MyApp
使用非法参数异常检查公共方法上的参数
严格不鼓励在公共方法上使用断言;因为报告的错误是在客户端代码中犯下的 - 诚实地告诉他们,当他们搞砸了时,提前告诉他们一个非法的论据。
public double toScale( int scaleDenominator ){
if( scaleDenominator > 0 ){
throw new IllegalArgumentException( "scaleDenominator must be greater than 0");
}
return 1 / (double) scaleDenominator;
}
在需要时使用 NullPointerException
如果可能的话,执行你自己的空检查;抛出一个 IllegalArgumentException 或 NullPointerException,其中包含有关出错的详细信息。
public double toScale( Integer scaleDenominator ){
if( scaleDenominator == null ){
throw new NullPointerException( "scaleDenominator must be provided");
}
if( scaleDenominator > 0 ){
throw new IllegalArgumentException( "scaleDenominator must be greater than 0");
}
return 1 / (double) scaleDenominator;
}