在Java中避免“!= null”语句?


原问题:

我整天都在用Java工作。在用Java编程时用的最多的语句(或者说代码片段),就是在使用一个对象前,我都会先测试 object != null(对象是否为空)这是为了避免抛空指针(NullPointerException) 的错误。我发现这样代码一点都不美观,并且可读性不高。

有没有好的选择可以避免掉这段代码?

更新:潘(Pan,人名),我也不是太清楚自己的问题。我想强调的是,如果你想要访问某个对象的字段或方法,对这个对象是否为null的测试是必要的。例如:
 
...
if (someobject != null) { 
    someobject.doCalc(); 
} 
...

在这种情况下,我不必知道对象是否为null,就可以避免空指针(NullPointerException)的错误。但因此,我的代码里就会满是这种测试。
不过还是非常感谢你的回答,我又得到了一些新的见解。


票选最高回答:

对我来说,这是个相当普遍的问题,并且是从初级到中级开发人员往往都要面对的:他们要么是不知道, 要么是不相信他们都在参与并过度检查来抵御null的出现 (这句真心是翻译残了,overcheck卡住我了。。。我只好理解成over check,希望有朋友指正) 。此外,在编写自己的代码时,他们往往依赖返回空值来指明(or 表示)一些东西,因此,这就需要调用者来检查空值(nulls)。

换种方式来说,当涉及到空值检查时会有两种情况:
  1. 空值是符合条件的有效响应;和
  2. 不是有效响应

第2种情况简单。要么用assert语句(断言)要么允许抛错(例如,NullPointerException空指针错误)Assertions是java1.4以后新增的一个没有被高度利用的java特性。语法如下:

        表达式1:assert *<condition>*
或者

        表达式2:assert *<condition>* : *<object>*


 <object>的toString()输出将会被包含在错误(error)中。

如果<condition>条件返回非真,一条assert语句将抛出一个错误(AssertionError) (注:<condition>表示一个boolean表达式)。默认情况下,Java是忽略Assertions的。你可以通过功能参数 -ea 开启assertions功能。你可以开启(关闭)某些类或包的assertion功能。这就意味着,在开发和测试时,你可以通过assertions功能来验证代码,并且在生产环境中禁用他们,虽然我的测试表明aseertions没有对性能的影响。(这句也翻译残了,~~~~(>_<)~~~~ )

在这种情况下不适用断言也是可以的:代码最终会运行出错。唯一的区别是,断言可能发生的更早些,通过更有意义的方式并且可能伴随着附加的信息,如果你没有预料到这种错误,这可以帮助你找出为什么错误会发生。

第一种情况稍微困难些。如果你在调用的时候,对代码没有控制,那你就完蛋了。如果null是有效的响应,你必须要检查它。

如果你确实对代码做了控制,那么(这是通常的情况),这就是另一回事儿了。避免用null作为响应。几乎不管什么时候,用返回集合的方法,很容易:返回空集(或者空数组)而不是返回nulls。
对于非空集合可能就要难一些。设想这样一个例子:如果你有这些接口

public interface Action {
  void doSomething();
}
public interface Parser {
  Action findAction(String userInput);
}

其中 Parser (解析器)接受原始用户的输入并找些事做,或许是你正在为某些东西实现一个命令行界面的时候。现在你可能会约定如果没有适当的操作那么就返回null。这就导致了你谈到的为空检查。

另一种解决方法是决不返回null,而是使用Null Object模式:

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;
    }
  }
}

设计1
Parser parser = ParserFactory.getParser();
if (parser == null) {
  // 现在怎么办?
  // 这里可能是一个null不是(或不应该是)有效响应的例子
}
Action action = parser.findAction(someInput);
if (action == null) {
 // do nothing
} else {
  action.doSomething();
}
设计2
ParserFactory.getParser().findAction(someInput).doSomething();

对比设计1和设计2,后者是一个更好一些的设计,它使得代码更加简洁。



随记:一是为了英文的进步,一是逼着自己回到技术上来。开始翻译stack overflow上的Highest voted的问题。刚刚开始,翻译错误和理解偏差难免,且翻且学习。




您可以对这个 SQL 查询进行一些优化,以提高性能和可读性。以下是一些建议: 1. 使用表的别名来提高可读性。例如,将 "eb_user" 表的别名设置为 "u",将 "eb_user_group" 表的别名设置为 "g",将 "eb_system_user_level" 表的别名设置为 "l"。 2. 尽量避免在 SQL 查询使用函数,因为函数的调用可能会降低查询性能。在这个查询,可以考虑将函数 CONCAT('%',nickname,'%') 移到 Java 代码进行拼接。 3. 对于 LIKE 操作符,可以考虑使用通配符的位置来优化查询。例如,如果您知道 nickname 参数通常在前缀位置,可以将查询条件改为 u.real_name LIKE CONCAT(nickname,'%')。 4. 如果可能的话,将参数作为预编译语句的绑定变量传递给查询。这有助于提高查询性能并防止 SQL 注入攻击。 5. 使用合适的索引来加速查询。根据查询条件和表结构,在各个表的关联字段上创建索引可以提高查询性能。 6. 如果可能的话,避免使用 OR 运算符,因为它可能会导致查询性能下降。如果能够确定一个字段的条件会更频繁地匹配,可以将其作为主要条件,并使用 UNION 或子查询来处理其他条件。 7. 定期进行数据库维护,包括统计信息更新和索引重建,以确保查询性能的稳定性。 请注意,这些只是一些建议,并且可能需要根据您的具体情况进行调整和测试。同时,还要考虑数据库的规模和负载情况来综合评估优化效果。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值