11

私は自分がこのようなメソッドを書いていることに気づきました:

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

6 に答える 6

9

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

}
于 2011-03-24T17:11:47.467 に答える
1

AppacheCommonStringUtils.isEmpty()メソッドを。と組み合わせることができますBeanUtils.getProperties()

于 2011-03-24T15:34:01.843 に答える
0

オブジェクトグラフ全体のコンテンツが完全に欠けているものがアプリケーションに侵入する状況を実際に想像することはできません。さらに、正確には何が「空」と見なされますか?それは文字列とコレクションを指すだけでしょうか?空白のみの文字列はカウントされますか?数字はどうですか...どんな数字でもオブジェクトは空ではなくなりますか、それとも-1のような特定の数字は空としてカウントされますか?さらに別の問題として、オブジェクトにコンテンツがないかどうかを知ることは一般的に有用ではないようです...通常、特定のフィールドに特定のデータなどがあることを確認する必要があります。私の意見では、このようないくつかの一般的な方法は理にかなっています。

たぶん、JSR-303のようなより完全な検証システムの方がうまくいくでしょう。そのためのリファレンス実装はHibernateValidatorです。

于 2011-03-24T15:55:13.340 に答える
0

ねえケビン、あなたが求めた方法のようなものを見たことがありません(私自身も興味があります)が、実行時にオブジェクトをクエリするためにリフレクションを使用することを検討しましたか?

于 2011-03-24T15:33:02.080 に答える
0

これを行うライブラリはわかりませんが、リフレクションを使用すると、自分で実装するのはそれほど難しくありません。クラスのgetterメソッドを簡単にループして、インスタンスに値が設定されているかどうかを判断できます。さらに、getterの戻り型に応じて結果を判断できます。

難しいのは、クラスのどのメンバーを「有用なデータ」と見なすかを定義することです。リスト、マップ、および配列を除外するだけでは、おそらく遠くまで行くことはできません。

私は実際に、適切な「有用な」メンバーを「マーク」するために、独自の注釈タイプを作成することを検討します(これは、リフレクションコードによって認識+処理される可能性があります)。影響を受けるクラスの数がわからないため、これが問題に対するエレガントなアプローチであるかどうかはわかりません。

于 2011-03-24T15:44:24.137 に答える
0

上記のユーティリティメソッドはどれもジェネリックにすることはできませんが。(私の知る限り)唯一の方法は、空のオブジェクトと比較することです。(プロパティが設定されていない)オブジェクトのインスタンスを作成し、「。equals」メソッドを使用して比較します。2つの等しい非空オブジェクトの場合はtrueに、2つの空のオブジェクトの場合はtrueにequalsが適切に実装されていることを確認してください。

于 2011-03-24T16:40:58.977 に答える