【问题标题】:How to null check and return a value in a generic way如何以通用方式进行空检查并返回值
【发布时间】:2021-01-15 03:27:34
【问题描述】:

我有一长串要从 JAXB 自动生成的类中进行的对象映射。

 customer.setCustomerId(rentalCustomer.getCustomerid().getValue()));
 customer.setCustomerName(rentalCustomer.getTradingname().getValue());
 customer.setVatNumber(rentalSearchCustomer.getVatNumber().getValue());
 ....
 ....

基本上我需要对所有字段进行空检查:

getValue(RentalCustomerIDType idType){
  if(idType != null){
    return idType.getValue();
  }
  else {
   return "";
 }
}

问题是这些类型太多了,而且它们都有不同的类型:RentalCustomerIDType、TradingType、VatNumberType..etc

是否有一种优雅的方法可以通过创建一个 GENERIC 方法来进行 null 检查并为 ALL 返回正确的值(也许使用 Java 功能库)?

【问题讨论】:

  • idType.getValue() 是否总是一个字符串?或者也可以是其他类型?
  • 好的,那么我们只需要找到您要调用的所有这些方法的共同点。这些类型是否都扩展了某个类或实现了某个接口?是否所有方法都命名为getValue()?否则我们只需要写出一个又大又长的 switch-case 语句。
  • @Spring 我建议不要对那些试图帮助你并提出澄清问题的人大喊大叫。
  • 好的,有点混乱。所有 getValue() 方法都返回一个字符串吗?如果没有,他们会返回什么。以及包含 getValue() 方法的类的示例。
  • @Spring 它让我明白了问题所在。对不起我的坚持。但这是一个有趣的问题,所以我将继续研究它。但我有一个简单的问题?您是否为具有 getValue() 方法的每种类型编写了类?还是每种类型都实现了一些指定getValue 方法的接口?

标签: java


【解决方案1】:

也许在生成类时使用反射并通过为字段分配非空值来消除所有空值?

Check an replace null values in multiple variables java

他们说(回答的人)他们强烈反对为此目的使用反射......但是......嗯。我已经做到了,它有效。

【讨论】:

    【解决方案2】:

    您可以使用泛型方法声明getValueFromAllObjects 方法,然后使用反射调用getValue 方法

    public static <T> String getValueFromAllObjects(T t) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
      if(t != null){
        return (String) t.getClass().getDeclaredMethod("getValue").invoke(t);
      }
      else {
       return "";
     }
    }
    

    请参阅https://stackoverflow.com/a/54883454/442256 了解反射替代方案。我刚刚在上面的代码中内联了一个示例

    【讨论】:

    • OP 说 请注意 getValue() 是特定于类型的。所以 getValue() 返回不同的类型。对于每种类型,您都需要其中一种方法。您不能将 String 分配给所有类型。
    • 我假设它是字符串,因为他在评论中澄清了 [这里] (stackoverflow.com/questions/65692652/…)
    • 那是给idType的。还有其他类型。
    • @WJS 在 getValue() 函数中返回一个空字符串 "" 意味着字符串
    • @Spring 不用担心,如果它有助于争论“for”反射的情况,JAXB 会大量使用它,Spring 等 DI 框架也是如此
    【解决方案3】:

    据我了解,您不想更改现有的自动生成的类。您可以做的是创建一个 CustomerWrapper 类,该类包装 Customer 并在 null 设置为字段时插入默认值。这是代码中的想法:

    public class CustomerWrapper() {
    
        private final Customer customer;
    
        public CustomerWrapper(Customer customer) {
            this.customer = customer;
        }
    
        public void setCustomerId(String id) {
            this.customer.setCustomerId(id == null ? "" : id);
        }
    
        // Insert other methods here.
    
    }
    

    【讨论】:

    • 编写一个处理所有字段的所有不同类型的包装器并不比检查空值更优雅
    【解决方案4】:

    可能是面向方面编程的一个案例,如果它的使用是一种选择:

    【讨论】:

      【解决方案5】:

      我猜你想使用类似的东西。在这里,我将 ResponseUserDto 作为我的 Pojo 类,以对其属性进行空值检查。

      private ResponseUserDto getValidNotNullPropertyObject(Object source) {
          final BeanWrapper src = new BeanWrapperImpl(source);
          Map < String, Object > result = new HashMap<>();
          for (PropertyDescriptor property: src.getPropertyDescriptors()) {
              if (src.getPropertyValue(property.getName()) == null) {
                  /* if(property.getPropertyType() == ?) {
                          //maybe do somethig here
                      }*/
                  result.put(property.getName(), ""); // this is start
              } else {
                  result.put(property.getName(), src.getPropertyValue(property.getName()));
              }
          }
          final ObjectMapper mapper = new ObjectMapper(); // Jackson's ObjectMapper
          final ResponseUserDto finalResult = mapper.convertValue(result, ResponseUserDto.class);
          return finalResult;
      }
      

      要使用它,你可以这样称呼它

      return this.getValidNotNullPropertyObject(responseUserDto);
      

      【讨论】:

        【解决方案6】:

        这就是你想要的。但是有一个警告。每种类型都必须实现提供getValue() 方法的相同接口。否则,您可能需要反思才能获得您怀疑的方法。但这里有一个供后代使用的解决方案。

        setType(rentalSearchCustomer::getCustomerid,
                customer::setCustomerId);
        setType(rentalSearchCustomer::getTradingname,
                customer::setCustomerName);
        setType(rentalSearchCustomer::getVatNumber,
                customer::setVatNumber);
        System.out.println(customer);
                
            
            
        public static <T extends GetValue> void setType(Supplier<T> sup,
                Consumer<String> con) {
            if (sup.get() == null) {
                con.accept("");
            } else {
                con.accept(sup.get().getValue());
            }
        }
            
        interface GetValue {
            public String getValue();
        }
        

        【讨论】:

        • 我认为您误解了这个问题。您的示例显示可选接受字符串您如何将 RentalSearchCustomerIDType 发送到您的 getValue 方法?并想象所有字段的类型都不同
        • thx 但它缺少我的自定义类型对象的 getValue() 方法请注意 getValue() 是特定于类型的
        猜你喜欢
        • 2015-01-03
        • 2019-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多