Commons方法测试一个空的Java对象图?

时间:2011-03-24 15:28:24

标签: java spring apache-commons utilities

我发现自己写的是这样的方法:

boolean isEmpty(MyStruct myStruct) {
  return (myStruct.getStringA() == null || myStruct.getStringA().isEmpty())
    && (myStruct.getListB() == null || myStruct.getListB().isEmpty());
}

然后想象这个结构有很多其他属性和其他嵌套列表,你可以想象这个方法变得非常大并且与数据模型紧密耦合。

Apache Commons,Spring或其他一些FOSS实用程序是否能够递归反射地遍历对象图并确定它基本上没有任何有用的数据,除了列表,数组,地图等的持有者?所以我可以写:

boolean isEmpty(MyStruct myStruct) {
  return MagicUtility.isObjectEmpty(myStruct);
}

6 个答案:

答案 0 :(得分:8)

感谢Vladimir指出我正确的方向(我给了你一个upvote!)虽然我的解决方案使用PropertyUtils而不是BeanUtils

我确实必须实施它,但并不难。这是解决方案。我只为字符串和列表做过,因为那是我现在碰巧遇到的。可以扩展为地图和阵列。

import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;

public class ObjectUtils {

  /**
   * Tests an object for logical emptiness. An object is considered logically empty if its public gettable property
   * values are all either null, empty Strings or Strings with just whitespace, or lists that are either empty or
   * contain only other logically empty objects.  Currently does not handle Maps or Arrays, just Lists.
   * 
   * @param object
   *          the Object to test
   * @return whether object is logically empty
   * 
   * @author Kevin Pauli
   */
  @SuppressWarnings("unchecked")
  public static boolean isObjectEmpty(Object object) {

    // null
    if (object == null) {
      return true;
    }

    // String
    else if (object instanceof String) {
      return StringUtils.isEmpty(StringUtils.trim((String) object));
    }

    // List
    else if (object instanceof List) {
      boolean allEntriesStillEmpty = true;
      final Iterator<Object> iter = ((List) object).iterator();
      while (allEntriesStillEmpty && iter.hasNext()) {
        final Object listEntry = iter.next();
        allEntriesStillEmpty = isObjectEmpty(listEntry);
      }
      return allEntriesStillEmpty;
    }

    // arbitrary Object
    else {
      try {
        boolean allPropertiesStillEmpty = true;
        final Map<String, Object> properties = PropertyUtils.describe(object);
        final Iterator<Entry<String, Object>> iter = properties.entrySet().iterator();
        while (allPropertiesStillEmpty && iter.hasNext()) {
          final Entry<String, Object> entry = iter.next();
          final String key = entry.getKey();
          final Object value = entry.getValue();

          // ignore the getClass() property
          if ("class".equals(key))
            continue;

          allPropertiesStillEmpty = isObjectEmpty(value);
        }
        return allPropertiesStillEmpty;
      } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
      } catch (InvocationTargetException e) {
        throw new RuntimeException(e);
      } catch (NoSuchMethodException e) {
        throw new RuntimeException(e);
      }
    }
  }

}

答案 1 :(得分:1)

您可以将Apache Common StringUtils.isEmpty()方法与BeanUtils.getProperties()结合使用。

答案 2 :(得分:0)

嘿凯文,没有看到任何类似你要求的方法(我自己也对此感兴趣),但是,您是否考虑过使用反射在运行时查询对象?

答案 3 :(得分:0)

我不知道这样做的库,但是使用反射,你自己实现起来并不难。 您可以轻松地循环遍历类的getter方法并确定实例是否具有值集,您可以根据getter的返回类型进一步确定结果。

困难的部分是定义您认为是“有用数据”的类的哪些成员。只是省略列表,地图和阵列可能不会让你走得太远。

我实际上会考虑编写自己的注释类型,以“标记”适当的“有用”成员(然后可以注意到+由反射代码处理)。我不知道这是否是一个优雅的方法来解决你的问题,因为我不知道有多少类受到影响。

答案 4 :(得分:0)

我无法想象一个完整对象图中完全没有任何内容的东西会进入应用程序的情况。究竟什么才算“空”?那只是引用字符串和集合吗?只有空格的字符串会计数吗?数字怎么样...任何数字都会使对象非空,或者像-1这样的特定数字是否为空?作为另一个问题,通常看起来对象中没有内容通常是有用的...通常你需要确保特定字段具有特定数据等。有太多可能性在我看来,这样的一般方法是有意义的。

也许像JSR-303这样更完整的验证系统会更好。该参考实现是Hibernate Validator

答案 5 :(得分:0)

虽然上述实用方法都不是通用的。 (据我所知)唯一的方法是与空对象进行比较。创建对象的实例(没有设置属性)并使用“.equals”方法进行比较。对于2个相等的非空对象,确保将equals正确实现为true。对于2个空对象,则为true。