【问题标题】:A suitable pattern instead of returning nulls一个合适的模式而不是返回空值
【发布时间】:2012-12-28 04:50:34
【问题描述】:

在这里使用什么模式比较好?

我不想返回空值,这感觉不对。

另一件事是,如果我想返回导致它为空的原因怎么办?如果调用者知道它为什么为空,它可以做一些额外的事情,所以我希望调用者知道它并以这种方式行事

Public CustomerDetails getCustomerDetails(){
   if(noCustomer){    
     ..log..etc..
     return null;
   }

   if(some other bad weird condition){    
     ..log..etc..
     return null;
   }

   CustomerDetails details= getCustomerDetailsFromSomewhere();

   if (details!=null){
      return details;
   }
   else {
     ..log..etc..
     return null;
   }

}

【问题讨论】:

  • 为什么你认为返回 null 不好??有什么具体原因吗?
  • 一种可能性是,您可以抛出IllegalArgumentException。或者创建您自己的 CustomException,并使用它。但是,相信我,这将花费您更多的时间而不是返回 null。现在为什么你不想返回 null?
  • @GanGnaMStYleOverFlowErroR 每次我必须调用它时我都会进行一次空检查,因此很容易出错,但主要原因是在这种情况下它只是“感觉”错误。我可能错了

标签: java design-patterns optimization


【解决方案1】:

我认为您有 3 个主要选择:

  • 如果 null 是有效状态,我认为返回 null 没有问题
  • 如果 null 是无效状态,则应抛出异常
  • 或使用Null object pattern

如果您使用的是谷歌Guava libraries,您也可以使用Optional 类。

【讨论】:

    【解决方案2】:

    Java 中更自然的方式是在错误条件下抛出异常。

    public CustomerDetails getCustomerDetails(){
       if(noCustomer){    
         ..log..etc..
         throw new NoSuchCustomer(customerName);
       }
    
       if(some other bad weird condition){    
         ..log..etc..
         throw new IllegalStateException("some other bad weird condition occurred");
       }
    
       CustomerDetails details= getCustomerDetailsFromSomewhere();
    
       if (details==null)
          throw new IllegalStateException("Failed to get customer details for "+ customerName);
    
       return details;
    }
    

    getCustomerDetailsFromSomewhere() 方法可以抛出异常而不是返回 null。

    【讨论】:

    • tnx,您能说说这种方法的优缺点,而不是使用空对象设计模式或使用反馈包装类
    • @Spring:异常用于表示异常的、非预期的情况。如果没有客户是正常情况,返回 null 或 Optional 就可以了。相反,如果没有客户,或者没有这种“糟糕的奇怪”情况,则可能会引发异常。如果你写了方法的契约,并描述了“noCustomer”和“bad奇怪的条件”实际上是什么,我们可以给你一个更好的建议。
    • @JB Nizet 那些是用户登录并且是用户授权检查,我需要向调用者类返回一个正确的 http 代码,因为它将被 Jersey 休息服务使用,还有很多其他的这些方法类似,我想将此服务方法与所有其他相关类分离,
    • @JB Nizet 在这种情况下编写了一个包装反馈类(如 Eng.Fouad 建议的),它通过返回适当的 Web 异常来处理这些情况,我认为这是要走的路
    【解决方案3】:

    如果你的意思是null 没有解释它的状态,你可以用另一个可以提供更多细节的类来包装CustomerDetails。例如:

    class Feedback()
    {
        private CustomerDetails result;
        private int status;
    
        public static final int STATUS_OK = 0;
        public static final int STATUS_NULL = 1;
        public static final int STATUS_NO_CUSTOMER = 2;
        public static final int STATUS_BAD_CONDITION = 3;
    
        public Feedback(CustomerDetails result, int status)
        {
            this.result = result;
            this.status= status;
        }
    
        public CustomerDetails getResult(){return result;}
        public int getStatus(){return status;}
    }
    

    改变你的方法:

    Public Feedback getCustomerDetails()
    {
       if(noCustomer)
       {
           ..log..etc..
           return new Feedback(null, Feeback.STATUS_NO_CUSTOMER);
       }
    
       if(some other bad weird condition)
       {
           ..log..etc..
           return new Feedback(null, Feeback.STATUS_BAD_CONDITION);
       }
    
       CustomerDetails details = getCustomerDetailsFromSomewhere();
    
       if(details != null)
       {
            return new Feedback(details, Feeback.STATUS_OK);
       }
       else
       {
           ..log..etc..
           return new Feedback(null, Feeback.STATUS_NULL);
       }
    }
    

    然后你可以通过feedback.getStatus()获取状态。

    【讨论】:

    • 我认为有一个小错误,您在 null 检查后返回了反馈对象的详细信息
    • 你能通过抛出一个自定义异常来比较这种方法吗?这对我来说看起来更简单
    • @Spring 通过抛出异常,调用者只能知道异常原因为String。但是使用反馈对象,调用者可以通过 int 知道确切原因,并以比解析字符串了解原因更好的方式(例如在 switch 块中)处理它。但是,这两种机制都是正确的,您可以选择满足您需求的一种。
    • @Spring 如果你抛出不同的异常而不是每次都抛出相同的异常,那么调用者可以通过多个catch语句知道确切的原因。
    • 实际上我会将它用于 Rest jersey,这取决于出错或正确的地方我想返回正确的 http 代码并抛出必要的异常,但想将这个类与休息调用分离
    【解决方案4】:

    试试 Guava 的 Optional。请参阅这篇关于避免 null 的文章:http://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained

    【讨论】:

      【解决方案5】:

      使用Google Guava Optional

      这会有所帮助。

      程序员使用 null 的许多情况是表示某种类型 缺席:也许在可能有价值的地方,有 没有,或者找不到。例如, Map.get 返回 null 当没有找到某个键​​的值时。

      Optional 是一种将可以为空的 T 引用替换为 非空值。 Optional 可以包含非空 T 引用 (在这种情况下,我们说引用是“存在的”),或者它可能包含 什么都没有(在这种情况下,我们说引用是“不存在的”)。它从来不是 表示“包含空值”。

      Optional<Integer> possible = Optional.of(5);
      possible.isPresent(); // returns true
      possible.get(); // returns 5
      

      【讨论】:

        【解决方案6】:

        你可以试试;

        CustomerDetails details = setDetailsToEmpty();
        

        或类似的东西。

        您仍然需要检查空客户详细信息或空客户详细信息。

        【讨论】:

          【解决方案7】:

          如果你真的不希望 null 创建一个特殊的 CustomerDetails 对象

          ...
                  public static final CustomerDetails EMPTY_CUSTOMER_DETAILS = new CustomerDetails();
          ...    
                  public CustomerDetails getCustomerDetails(){
                      ...
                      if (details!=null){
                          return details;
                      }
                      ...
                      return EMPTY_CUSTOMER_DETAILS;
          

          【讨论】:

            猜你喜欢
            • 2020-05-15
            • 1970-01-01
            • 1970-01-01
            • 2021-10-08
            • 1970-01-01
            • 1970-01-01
            • 2021-07-17
            • 1970-01-01
            • 2021-10-22
            相关资源
            最近更新 更多