12

この質問があります。しかし、正確な用語がわからないので、説明するのは難しいでしょう。誰かが理解してくれることを願っています。できる限り説明しようと思います。これが大きく関係しているような気がしますparsing

2つのクラスがあるとします。そして、両方のクラスには、いくつかの変数、たとえば文字列 (簡単にするために、変数の型は何でもかまいません) があり、それらは似た名前を持っています。

Eg:
    class ClassA{
        String x,y,z;
    }

    class ClassB{
        String x,y,z;
    }

今、私が必要としているのは、あるクラスの変数値の値を、変数に対応する他のクラスにコピーする必要があるということです。

Eg:
    ClassA aa=new ClassA();
    ClassB bb=new ClassB();
    //set bb's variables
    aa.x=bb.x;
    aa.y=bb.y;
    aa.z=bb.z;

そのように。

ただし、必要なのは上記の方法ではないことに注意してください。単純なメソッドを記述して、渡された名前で関連変数を識別できるようになることを願っています。次に、それに応じて値の割り当てを行います。

私のイメージした方法はこんな感じです。

void assign(String val){        
    // aa.<val>=val
}

たとえば、メソッドに渡すbb.xと、割り当てが行われます。assign(...)aa.x=bb.x

これが十分に明確であることを願っています。これを説明するより良い方法があるはずです。誰かがそれを知っている場合は、投稿(+タイトル)を編集してより明確にしてください(ただし、私の考えは保存してください)。

これを達成する方法があれば教えてください。

ありがとう!

4

4 に答える 4

13

Dozer は問題ありません。Jean-Remy の回答を参照してください。

また、変数が JavaBeans 標準に従ってゲッターとセッターを持っている場合、Apache Commons / BeanUtilsなど、役立つテクノロジーがいくつかあります。

サンプルコード (未テスト):

final Map<String, Object> aProps = BeanUtils.describe(a);
final Map<String, Object> bProps = BeanUtils.describe(b);
aProps.keySet().retainAll(bProps.keySet());
for (Entry<String, Object> entry : aProps.entrySet()) {
    BeanUtils.setProperty(b,entry.getKey(), entry.getValue());
}

アップデート:

ゲッターとセッターがない場合は、フィールドに共通の名前と型がある限り、あるクラスから別のクラスにフィールド値をコピーする簡単なハックを次に示します。私はそれをテストしていませんが、出発点としては問題ないはずです:

public final class Copier {

    public static void copy(final Object from, final Object to) {
        Map<String, Field> fromFields = analyze(from);
        Map<String, Field> toFields = analyze(to);
        fromFields.keySet().retainAll(toFields.keySet());
        for (Entry<String, Field> fromFieldEntry : fromFields.entrySet()) {
            final String name = fromFieldEntry.getKey();
            final Field sourceField = fromFieldEntry.getValue();
            final Field targetField = toFields.get(name);
            if (targetField.getType().isAssignableFrom(sourceField.getType())) {
                sourceField.setAccessible(true);
                if (Modifier.isFinal(targetField.getModifiers())) continue;
                targetField.setAccessible(true);
                try {
                    targetField.set(to, sourceField.get(from));
                } catch (IllegalAccessException e) {
                    throw new IllegalStateException("Can't access field!");
                }
            }
        }
    }

    private static Map<String, Field> analyze(Object object) {
        if (object == null) throw new NullPointerException();

        Map<String, Field> map = new TreeMap<String, Field>();

        Class<?> current = object.getClass();
        while (current != Object.class) {
            for (Field field : current.getDeclaredFields()) {
                if (!Modifier.isStatic(field.getModifiers())) {
                    if (!map.containsKey(field.getName())) {
                        map.put(field.getName(), field);
                    }
                }
            }
            current = current.getSuperclass();
        }
        return map;
    }
}

呼び出し構文:

Copier.copy(sourceObject, targetObject);
于 2012-08-10T11:20:00.333 に答える
7

ドーザーについて聞いたことがありますか?: http://dozer.sourceforge.net/

ドーザー

Dozer は、あるオブジェクトから別のオブジェクトにデータを再帰的にコピーする Java Bean から Java Bean へのマッパーです。通常、これらの Java Bean は異なる複合型になります。

Dozer は、単純なプロパティ マッピング、複合型マッピング、双方向マッピング、暗黙的明示的マッピング、および再帰的マッピングをサポートしています。これには、要素レベルでのマッピングも必要なコレクション属性のマッピングが含まれます。

Dozer を使用すると、Java Bean をマップできます。

  • それらの名前を使用する (暗黙のマッピング)、つまり ClassA.x を ClassB.x にマッピングする
  • (非常に単純な)xmlまたは注釈構成を使用して、異なる構造(明示的なマッピング)を異なる名前でマッピングする機能を提供します。

ライブラリ サイトの XML の例を次に示します。

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://dozer.sourceforge.net
          http://dozer.sourceforge.net/schema/beanmapping.xsd">
          
  <mapping> 
    <class-a>org.dozer.vo.TestObject</class-a>
    <class-b>org.dozer.vo.TestObjectPrime</class-b>   
    <field>
      <a>one</a>
      <b>onePrime</b>
    </field>
  </mapping>  

      <!-- SNIP ... -->

</mappings>

これにより、オブジェクト org.dozer.vo.TestObject が TestObjectPrime にマップされ、(あなたの場合のように) 同一のすべての変数が一緒にマップされ、変数 TestObjectFoo.oneFoo が TestObjectFooPrime.oneFooPrime にマップされます。

いいですね。

于 2012-08-10T11:11:32.980 に答える
3

新しい答え。

かなり簡単に思えるので、ドーバーを調べることをお勧めします。

2 番目のオプションは、クラスを XML にシリアル化し、一致するメンバーでのみターゲット クラスに逆シリアル化することです。

コメントで言及した 3 番目のオプションは、リフレクションを使用することでした - http://java.sun.com/developer/technicalArticles/ALT/Reflection/

この手法により、イントロスペクションと呼ばれる優れた設計パターンが可能になります - Java のイントロスペクションとリフレクションにより、特定のクラスのメンバーを発見することができます...

そうは言っても、単に ClassA のメンバーを「発見」し、ArrayList にそれらの名前を入力し、ClassB のメンバーを発見し、別の ArrayList にそれらの名前を入力し、交差するセットの値をコピーするだけです。少なくともそれが私の考えです。

于 2012-08-10T11:12:19.323 に答える
3

ここを見てください。使うだけBeanUtils.copyProperties(newObject, oldObject);

于 2017-03-21T06:50:51.883 に答える