java如不想么每次都判空 if(o !=null) 怎么做?

涉及到对象操作 object.xxxx(),如果对象为null则会抛异常,如果每次都if(o !=null) 代码很丑陋

一种做法是创建对象或者方法返回对象时都new一个对象而不是返回null
不过这样有时也不太好,比如结果为空的时候返回null更合理一点

有更好的建议么 ?

阅读 21.9k
评论
    14 个回答

    这是是工程设计上常见的问题,一般的解决方案就是 @特价萝卜 所说的NullObject模式。本来想投 @特价萝卜 的答案赞成票,但纠结良久还是觉得说得有些复杂了。

    简单来说就是有一个NullObject与原有业务对象实现相同的接口(或继承同一个父类),让客户端调用时可以无感知(也不必判定null)

    有一个很好的例子就是著名JSON解析框架Jackson。以下代码是Jackson从一段JSON中获取其一级子节点lv1下的二级子节点lv2的内容:

    JsonNode root = ...;
    JsonNode child = root.get("lv1").get("lv2");

    以上代码很可能遇到lv1不存在的情况,因此第一个get()就会返回null,那么第二个get()执行时自然就抛出NullPointerException了。为了解决这个问题,作者提供了path方法来替代get方法:

    JsonNode root = ...;
    JsonNode child = root.path("lv1").path("lv2");

    当lv1不存在时,path()返回一个JsonNode的子类叫做MissingNode(但客户端暂时无需知道),MissingNode的path方法则继续返回MissingNode,这样无论这个链式调用写多长都不会抛出任何异常。

    直到最后客户端调用完成后检查返回结果是否为MissingNode:

    if (child.isMissingNode()) { ... }

      有一种模式叫NullObject,意思就是建立一个专用的空对象,以此来代表结果为空。比如这样:

      public interface MyObj {
        public String someOp();
      }
      
      public class NullObj implements MyObj {
        public String someOp() {
          return "It's a content of NullObj"; // 或者抛出一个特定异常,又或者打印出一条警告信息
        }
      }
      
      public class NormalObj implements MyObj {
        public String someOp() {
          String result = null;
          // 执行一些正常的代码
          return result;
        }
      }

      用法:

      1、建立全局常量:

      public enum Constants { //这种写单例的方式在《Effective Java》中被推荐过,非常好的实现方式。
        ONE;
        public final MyObj NULL_OBJ = new NullObj(); //如果用enum写单例的话这里就不用static修饰符了。
      }

      2、被调用的代码在条件符合的时候返回NullObj:

      public class Server {
      ...
        public MyObj receive(String param) {
          if (param == null) {
            System.out.println("..."); //记录一些log
            return Constants.ONE.NULL_OBJ;
          }
          MyObj result = null;
          ...
          return result;
        }
      ...
      }

      3、在调用方:

      public class Client {
        public result send(String content) {
          Server server = null;
          String result = null;
          try {
            ... //初始化server
            MyObj myObj = server.receive(content);
            result = myObj.someOp(); //如果你前面选择的是抛出特定异常,则这行代码就必须放在try-catch语句块中了
            // 后续的操作就非常灵活了,或比对结果字符串或catch特定异常,取决于你的NullObj是怎么实现的
            ...
          } catch (Exception e) {
            ... 
          }
        }
      }

      当然,通过捕获异常来进行流程控制的方式是不被推荐的。NullObject很灵活,可以做出很多扩展性很强的实现方案。

        • 4.6k
          • 2
          • 新人请关照

          1. 如果被调用方法返回可能为null的话,建议每次使用 if(null == o){ //异常分支处理 } 然后再进行正常分支的逻辑代码编写,这样就不会使代码多层条件判断嵌套;代码会美观一些。
          2. 一般对于复杂的调用建议返回结果对象,这样可以封装被调用方法需要返回的各种异常状态等信息,便于调用端精细化处理。

            • 858

            三元运算符

              • 2.6k

              返回为null时改为抛出异常不就好了。。。

                你可以试试看用underscore.js,我一般判断的方法就是

                if (!_.isNull(object.xxx()){
                //非null,继续执行
                }

                  • 4
                  • 新人请关照

                  apache 的commons 中有一些工具类可以使用

                    在Java的工程实践中,需要经常判断对象是否为null是一个常见都困扰,根据个人经验,我通常不做任何的判断,任其抛出NullPointerException。因为方法或者构造函数中允许参数为null通常并不是一个好的工程设计。或许有人会以为了增加系统的容错性,所以允许null参数来反驳,这也有一定的道理,不过这还是取决于你的类设计。我的经验是,通常要将你所设计的类划分职责,越是倾向于底层逻辑、基础数据操作的类,可以适当的容忍null参数;越是倾向于重要业务逻辑的类,通常不容忍null参数。在处理NullPointerException或者其他RuntimeException的时候,应该有一个统一的错误处理策略。就像Spring中对于Exception的策略一样,所有的方法都抛出RuntimeException。

                    多说一句,这个话题其实涉及到如何设计你的系统中的错误处理机制。这个绝对是见仁见智的事情,不会有一个绝对正确的答案。

                      • 1
                      • 新人请关照

                      assert o != null ; 不知道可不可行?

                        把null判断交给调用方。

                          参见guava中的optional

                            public boolean isNullObject(){
                                    boolean isNull=true;//默认为空
                                    Field[] at = this.getClass().getDeclaredFields();
                                    for (Field field : at) {
                                        field.setAccessible(true);
                                        try {
                                            if (field.get(this) != null){
                                                isNull=false;//只要有一个属性非空,那就认为非空了
                                                break;
                                            }
                                        } catch (Exception e) {
                            
                                        } 
                                    }
                                    return isNull;
                                }
                            
                              • 133

                              改用Scala吧!

                                撰写回答

                                登录后参与交流、获取后续更新提醒