java如何避免null_Java 如何避免使用 “!=null” 语句?

本文探讨了如何通过使用assert语句、返回空集合而非null、遵循NullObject模式以及利用IDE工具进行编译器检查,来优化代码并减少NullPointerException。作者提供了实例和最佳实践,强调了设计良好接口和明确错误信息的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

我使用object!= null来避免NullPointerException。

有没有一个更好的选择呢?

例如:

if (someobject != null) {

someobject.doCalc();

}

这避免了一个NullPointerException,当它不知道对象是否为null时。

#1 热门回答(2367 赞)

对我而言,这听起来像是一个相当普遍的问题,初级到中级开发人员往往会在某些时候面临这样的问题:他们要么不知道,要么不信任他们正在参与的合同,并且防御性地检查空值。此外,在编写自己的代码时,他们倾向于依靠返回空值来指示某些事情,因此需要调用者检查空值。

换句话说,有两种情况出现空检查:

无效是合同方面的有效答复;和

它不是一个有效的回应。

(2)很容易。使用assert语句(断言)或允许失败(例如,NullPointerException)。断言是1.4中添加的一个使用率很低的Java特性。语法是:

assert

要么

assert :

其中是一个布尔表达式,是一个对象,它的toString()方法的输出将包含在错误中。

如果条件不成立,assert语句会抛出Error(AssertionError)。默认情况下,Java会忽略断言。您可以通过将选项-ea传递给JVM来启用断言。您可以启用和禁用单个类和包的声明。这意味着您可以在开发和测试时使用断言验证代码,并在生产环境中禁用它们,尽管我的测试显示接近断言的性能影响。

在这种情况下不使用断言是可以的,因为代码只会失败,如果使用断言就会发生这种情况。唯一的区别是,断言可能会更快地发生,并且可能以更有意义的方式并可能带有额外的信息,这可能会帮助您找出如果您不期待它发生的原因。

(1)有点困难。如果你无法控制你打电话的代码,那么你就被卡住了。如果null是有效的响应,则必须检查它。

但是,如果它是你控制的代码(这通常是这种情况),那么这是一个不同的故事。避免使用空值作为回应。使用返回集合的方法,很简单:几乎总是返回空集合(或数组)而不是空值。

非集合可能会更困难。考虑这个例子:如果你有这些接口:

public interface Action {

void doSomething();

}

public interface Parser {

Action findAction(String userInput);

}

Parser需要原始的用户输入并找到要做的事情,或许你正在实现一些命令行界面。现在您可以制定合同,如果没有适当的操作,它将返回null。这导致你正在谈论的空检查。

另一种解决方案是永远不会返回null,而是使用Null Object pattern:

public class MyParser implements Parser {

private static Action DO_NOTHING = new Action() {

public void doSomething() { /* do nothing */ }

};

public Action findAction(String userInput) {

// ...

if ( /* we can't find any actions */ ) {

return DO_NOTHING;

}

}

}

比较:

Parser parser = ParserFactory.getParser();

if (parser == null) {

// now what?

// this would be an example of where null isn't (or shouldn't be) a valid response

}

Action action = parser.findAction(someInput);

if (action == null) {

// do nothing

} else {

action.doSomething();

}

ParserFactory.getParser().findAction(someInput).doSomething();

这是一个更好的设计,因为它导致更简洁的代码。

也就是说,对于findAction()方法来说,抛出一个有意义的错误消息的Exception是完全合适的 - 特别是在这种情况下,您依赖于用户输入。 findAction方法抛出一个Exception比调用方法抛出一个简单的NullPointerException没有任何解释更好。

try {

ParserFactory.getParser().findAction(someInput).doSomething();

} catch(ActionNotFoundException anfe) {

userConsole.err(anfe.getMessage());

}

或者,如果您认为try / catch机制太难看了,而不是Do Nothing,您的默认操作应该向用户提供反馈。

public Action findAction(final String userInput) {

/* Code to return requested Action if found */

return new Action() {

public void doSomething() {

userConsole.err("Action not found: " + userInput);

}

}

}

#2 热门回答(510 赞)

如果您使用(或计划使用)诸如47216004,Eclipse或Netbeans之类的Java IDE或者findbugs之类的工具,那么您可以使用注释来解决此问题。

基本上,你有@ Nullable和@NotNull。

您可以在方法和参数中使用,如下所示:

@NotNull public static String helloWorld() {

return "Hello World";

}

要么

@Nullable public static String helloWorld() {

return "Hello World";

}

第二个例子不能编译(在IntelliJ IDEA中)。

当你在另一段代码中使用第一个helloWorld()函数时:

public static void main(String[] args)

{

String result = helloWorld();

if(result != null) {

System.out.println(result);

}

}

现在IntelliJ IDEA编译器会告诉你这个检查是无用的,因为helloWorld()函数永远不会返回null。

使用参数

void someMethod(@NotNull someParameter) { }

如果你写了类似的东西:

someMethod(null);

这不会编译。

最后一个使用@ Nullable的例子

@Nullable iWantToDestroyEverything() { return null; }

这样做

iWantToDestroyEverything().something();

你可以确定这不会发生。 :)

这是让编译器检查比平时更多的东西,并强制您的合约变得更强大的好方法。不幸的是,它并没有得到所有编译器的支持。

在IntelliJ IDEA 10.5及以上版本中,他们增加了对任何其他@ Nullable``@NotNull实现的支持。

#3 热门回答(282 赞)

##如果空值不被允许

如果你的方法是从外部调用的,那么从这样的事情开始:

public void method(Object object) {

if (object == null) {

throw new IllegalArgumentException("...");

}

然后,在该方法的其余部分,你会知道object不是null。

如果它是一个内部方法(不是API的一部分),只需记录它不能为null,就是这样。

例:

public String getFirst3Chars(String text) {

return text.subString(0, 3);

}

但是,如果你的方法只传递了值,并且下一个方法将其传递,那么它可能会产生问题。在这种情况下,你可能想要按照上面的方法检查参数。

##如果允许为null

这真的取决于。如果发现我经常做这样的事情:

if (object == null) {

// something

} else {

// something else

}

所以我分支,做两件完全不同的事情。没有丑陋的代码片段,因为根据数据我确实需要做两件不同的事情。例如,我应该处理输入,还是应该计算一个很好的默认值?

我实际上很少使用这个成语“if(object!= null && ...`”。

如果你展示了你通常使用习惯用法的例子,那么给你例子可能会更容易一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值