Rol*_*lig 23 java optimization coding-style nullpointerexception
有一些模式用于检查方法的参数是否已null赋值.
首先是经典之作.它在自制代码中很常见,并且很明显可以理解.
public void method1(String arg) {
if (arg == null) {
throw new NullPointerException("arg");
}
}
Run Code Online (Sandbox Code Playgroud)
其次,您可以使用现有框架.该代码看起来更好一点,因为它只占用一行.缺点是它可能会调用另一个方法,这可能会使代码运行得慢一些,具体取决于编译器.
public void method2(String arg) {
Assert.notNull(arg, "arg");
}
Run Code Online (Sandbox Code Playgroud)
第三,你可以尝试调用一个没有副作用的方法.这可能看起来很奇怪,但它比上述版本的令牌更少.
public void method3(String arg) {
arg.getClass();
}
Run Code Online (Sandbox Code Playgroud)
我没有看到广泛使用的第三种模式,感觉就像我自己发明了它一样.我喜欢它的简洁性,因为编译器很有可能完全优化它或将其转换为单个机器指令.我还用行号信息编译我的代码,所以如果NullPointerException抛出一个,我可以追溯到确切的变量,因为我每行只有一个这样的检查.
您更喜欢哪种支票,为什么?
Ber*_*t F 22
方法#3: arg.getClass();很聪明,但除非这个成语被广泛采用,否则我更喜欢更清晰,更冗长的方法而不是保存一些字符.我是一个"写一次,读很多"的程序员.
其他方法是自我记录:可以使用日志消息来澄清发生的事情 - 在阅读代码时以及在运行时使用此日志消息. arg.getClass()就目前而言,并非自我记录.你可以使用评论至少o澄清代码的评论者:
arg.getClass(); // null check
Run Code Online (Sandbox Code Playgroud)
但是你仍然没有机会像运行其他方法那样在运行时中放置特定的消息.
方法#1 vs#2(null-check + NPE/IAE vs assert):我尝试遵循这样的指导方针:
http://data.opengeo.org/GEOT-290810-1755-708.pdf
使用assert来检查私有方法的参数
assert param > 0;
使用null check + IllegalArgumentException检查公共方法的参数
if (param == null) throw new IllegalArgumentException("param cannot be null");
在需要的地方使用null check + NullPointerException
if (getChild() == null) throw new NullPointerException("node must have children");
但是,由于这个问题可能是关于null最有效地捕获潜在问题,所以我不得不提到我首选的处理方法null是使用静态分析,例如类型注释(例如@NonNull) JSR-305.我最喜欢的检查工具是:
Checker框架:
Java的自定义可插入类型
https://checkerframework.org/manual/#checker-guarantees
如果是我的项目(例如,不是具有公共API的库),并且我可以在整个过程中使用Checker Framework:
我可以在API中更清楚地记录我的意图(例如,这个参数可能不是null(默认值),但是这个可能是null(@Nullable;方法可能返回null;等等).这个注释在声明中是正确的,而不是离Javadoc越来越远,因此更有可能得到维护.
静态分析比任何运行时检查更有效
静态分析会提前标记潜在的逻辑缺陷(例如,我尝试将一个可能为null的变量传递给只接受非null参数的方法),而不是依赖于运行时发生的问题.
另一个好处是该工具允许我将注释放在注释中(例如`/ @Nullable /),因此我的库代码可以与类型注释项目和非类型注释项目兼容(不是我有任何这些).
如果链接再次死亡,这里是GeoTools开发人员指南的部分:
http://data.opengeo.org/GEOT-290810-1755-708.pdf
5.1.7使用断言,IllegalArgumentException和NPE
Java语言已经有几年了,现在可以使用断言关键字; 此关键字可用于执行仅调试检查.虽然此工具有多种用途,但常见的方法是检查私有(非公共)方法的方法参数.其他用途是后置条件和不变量.
参考: 使用断言编程
前置条件(如私有方法中的参数检查)通常是断言的简单目标.后置条件和不变量有时不那么直接但更有价值,因为非平凡条件有更多风险被打破.
使用Assert检查私有方法上的参数
private double scale( int scaleDenominator ){
assert scaleDenominator > 0;
return 1 / (double) scaleDenominator;
}
Run Code Online (Sandbox Code Playgroud)
您可以使用以下命令行参数启用断言:
java -ea MyApp
Run Code Online (Sandbox Code Playgroud)
您可以使用以下命令行参数仅转换GeoTools断言:
java -ea:org.geotools MyApp
Run Code Online (Sandbox Code Playgroud)
您可以禁用特定包的断言,如下所示:
java -ea:org.geotools -da:org.geotools.referencing MyApp
Run Code Online (Sandbox Code Playgroud)
使用IllegalArgumentExceptions检查公共方法上的参数
严格禁止在公共方法上使用断言; 因为报告的错误是在客户端代码中进行的 - 说实话,当他们搞砸了时就告诉他们IllegalArgumentException.
public double toScale( int scaleDenominator ){
if( scaleDenominator > 0 ){
throw new IllegalArgumentException( "scaleDenominator must be greater than 0");
}
return 1 / (double) scaleDenominator;
}
Run Code Online (Sandbox Code Playgroud)
在需要时使用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;
}
Run Code Online (Sandbox Code Playgroud)
Wil*_*mpt 12
你不是过早地优化biiiiiiiiiiiiit !?
我会用第一个.它简洁明了.
我很少使用Java,但我认为有一种方法可以让Assert只在调试版本上运行,所以这是一个禁忌.
第三个给了我毛骨悚然,我想如果我在代码中看到它,我会立即诉诸暴力.它完全不清楚它在做什么.
你不应该抛出NullPointerException.如果你想要一个NullPointerException,只是不要检查该值,当参数为null并且你试图取消引用它时它将自动抛出.
查看apache commons lang Validate和StringUtils类.
Validate.notNull(variable)如果"variable"为null,它将抛出IllegalArgumentException.
Validate.notEmpty(variable)如果"variable"为空(null或零长度",则会抛出IllegalArgumentException.
也许更好:
String trimmedValue = StringUtils.trimToEmpty(variable)将保证"trimmedValue"永远不为null.如果"variable"为null,则"trimmedValue"将为空字符串("") .
您可以使用Objects Utility Class.
public void method1(String arg) {
Objects.requireNonNull(arg);
}
Run Code Online (Sandbox Code Playgroud)
见http://docs.oracle.com/javase/7/docs/api/java/util/Objects.html#requireNonNull%28T%29
| 归档时间: |
|
| 查看次数: |
33709 次 |
| 最近记录: |