3

特定の Java クラスのインスタンスを、プリミティブ型のみを含む別のインスタンスに「フラット化」/変換したいと考えています。

まだプリミティブ型ではないオブジェクトのすべてのフィールドも再帰的にフラット化する必要があるため、結果のオブジェクトには元のオブジェクトのフラット化されたビューがプリミティブ型のみで含まれます。

たとえば、次のクラスがあるとします。

class Element {
  int id_;
  Position position_;
}

class Position {
  int x_;
  int y_;
}

結果のインスタンスは次のタイプになります。

class FlattenedElement {
  int id_;

  int x_;
  int y_;
}

そして、私はそのような振る舞いを期待します:

Element e = new Person ( 42, new Position(0, 0) );
FlattenedElement fe = e.flatten();

それができるツール/ライブラリはありますか?

それとも、リフレクション API を使用して独自のフラットナーを作成する必要がありますか?

-- 以下のほとんどのコメントを編集 --

Stringand との混同を避けるために例を変更しましたbyte(文字列を扱う必要はありません)。

結果の変換でデータのセマンティクスを維持する必要があります。出力プリミティブ型データは、プリミティブ データ型のみを理解する OpenCL を使用した並列計算に直接関与します。

つまり、カプセル化を解除して、クラス階層に埋め込まれたプリミティブ データ型を直接操作する必要があります。

4

3 に答える 3

1

これを行うことはできますが、Javaassist などの新しいクラスを作成するには、サード パーティのライブラリが必要になります。フラット化するクラスをイントロスペクトするには、一部のユーザーが既に述べたようにリフレクションを使用します。これが私があなたのために書いた別の例です:

public static Class flatten( Class classToFlatten ) {

    for ( Field f : classToFlatten.getDeclaredFields() ) {

        Class type = f.getType();
        String name = f.getName();
        int modifiersConfig = f.getModifiers();

        // extract all modifiers here (using the isXXX methods of the Modifier class)
        System.out.print( Modifier.isPrivate( modifiersConfig ) ? "private" : "" );
        System.out.print( " " + type );
        System.out.print( " " + name );
        System.out.println();

        if ( type.isPrimitive() ) {
            // primitive type.
            // does not need to be converted.
            // insert in the new class as it is (using Javaassist).
        } else {

            // no primitive type.
            // needs to be converted and tested.
            // insert in the new class after the conversion (using Javaassist).

            // convert rules...
            switch ( type.getSimpleName() ) {

                case "String":
                    // insert in the new class a array of chars.
                    break;

                // cases to test if the field is a wrapper (Integer, Long, etc.).

                // other rules tha you need here...

            }

            // here you need to use recursion...
            // you can use this method, but you will need to create
            // a new parameter, passing the class that is been built
            // to insert new fields in it (relative to the type that is been
            // reflected)

        }
    }

    // return the new class here and outside the method, use the newInstance
    // method to create new instances of this class
    return null;

}

これで必要なことができるようになると思いますが、なぜこれが必要なのかを考えています。再帰的にフレット化されるタイプの配列がある場合、いくつかの問題が発生します。これは、タイプを解決するために「バックトラック」する必要があるか、フラット化アルゴリズムを何度か実行する必要があるためです。ジェネリック、内部クラス、メソッド、およびあらゆる種類のクラス メンバーを使用すると、同じ問題が発生します。これが不可能だと言っているわけではありませんが、多くの時間を消費するので、一部のユーザーがすでに言ったように、もっと簡単な方法で問題を解決できるかもしれません。そうですね、あなたが必要なことをしてくれることを願っています。できれば結果を知りたいです! あなたのソリューションが新しいライブラリの種になるかもしれません! わかりました、ブレインストーミングは十分です :D ここにいくつかのリンクがあります。

Javaassist ライブラリは、ここからダウンロードできます。

ここでは、簡単なチュートリアルを見ることができます。Javaassist API はチュートリアルの作成以降に改善されている可能性があるため、これを最初にのみ使用することをお勧めします。したがって、これを読んだ後、(可能であれば) コードをリファクタリングし、ライブラリ ドキュメントを読んでください。

于 2012-07-15T15:40:19.080 に答える
0

リフレクションを使用する必要があります

小さなサンプルを見て、フィールドの名前を返します。

したがって、このフィールドの値を取得するには、返す必要がありますf[i].get(Object)

于 2012-07-15T15:14:19.893 に答える
0

さて、私の視点から、1 つの方法は次のようになります。

public class Person {
    String name;
    Atring address;

    public FlattenedPerson flatten() {
        FlattenedPerson fp = new FlattenedPerson(this.name.getBytes(), this.houseNumber, this.address.getStreet.getBytes(), this.address.getTown.getBytes());
        return fp;
    }
}
于 2012-07-15T10:37:11.100 に答える