5

ビジネス オブジェクトfetchObjects(String)の配列を返すメソッドがあります。Contractパラメータは、className返すべきビジネスオブジェクトの種類を教えてくれます (もちろん、これはContracts を返すと言ったので、この解釈されたケースでは意味がありませんが、基本的には実際のシナリオでの状況です)。そこで、どこかからエントリのセットを取得し、コレクションのエントリのクラスをロードします (そのタイプは で指定されますclassName)。

ここで、返す配列を作成する必要があるため、SettoArray(T[])メソッドを使用します。リフレクションを使用して、空の Contracts 配列を作成します。しかし、これは私に static 型の値を与えますObject! 次に、適切な型にキャストする必要があります。この場合はContract[](下のリストの「アスタリスクの下線」の部分を参照)。

私の質問は次のとおりです。Contract[]リストで行っているようにキャストする方法と方法はありますが、配列要素 ( ) の型ContractclassNameを(または)のみentriesTypeで決定しますか? 言い換えれば、私がやりたいことは、基本的に次のようにキャストすること(entriesType[]) valueWithStaticTypeObjectです。classnameContract

これはどういうわけか本質的に不可能ですか、それとも何とかできるのでしょうか? たぶんジェネリックを使用していますか?

package xx.testcode;

import java.util.HashSet;
import java.util.Set;

class TypedArrayReflection {

    public static void main(String[] args) {
        try {
            Contract[] contracts = fetchObjects("Contract");
            System.out.println(contracts.length);
        } catch (ClassNotFoundException e) {}
    }

    static Contract[] fetchObjects(String className) throws ClassNotFoundException {
        Class<?> entriesType = Class.forName("xx.testcode."+className);
        Set<?> entries = ObjectManager.getEntrySet(className); 
        return entries.toArray( 
                (Contract[]) java.lang.reflect.Array.newInstance(
                /********/          entriesType, entries.size()) );
    }
}

class Contract { } // business object

class ObjectManager {
    static Set<?> getEntrySet(String className) {
        if (className.equals("Contract"))
            return new HashSet<Contract>();
        return null; // Error
    }
}

ありがとう。


更新: CodeIdoltoArrayから取得したタイプセーフなメソッドを使用して、メソッドを次のように更新しました。fetchObjects

static Contract[] fetchObjects(String className) throws ClassNotFoundException {
    Class<?> entriesType = Class.forName("xx.testcode."+className);
    Set<?> entries = ObjectManager.getEntrySet(className);
    return toArray(entries, entriesType); // compile error
    // -> "method not applicable for (Set<capture#3-of ?>, Class<capture#4-of ?>)"
}

public static <T> T[] toArray(Collection<T> c, Class<T> k) {
    T[] a = (T[]) java.lang.reflect.Array.newInstance(k, c.size());
    int i = 0;
    for (T x : c)
        a[i++] = x;
    return a;
}

コメントで引用されているコンパイラ エラーを取り除くにはどうすればよいですか? これが機能するように、メソッドSet<Contract>の戻り値の型を絶対に指定する必要がありますか? getEntrySetご指摘ありがとうございます。

4

2 に答える 2

8

クラス名ではなく、クラスをパラメータとして使用できます。

   static <T extends Contract> T[] buildArray(Class<T> clazz){
     ArrayList<T> l=new ArrayList<T>();
     return l.toArray((T[]) java.lang.reflect.Array.newInstance(clazz, l.size()));
   }

編集:(ヤンのコメントを読んだ後)

いいえ、変数の値でジェネリック型を使用することはできません。

于 2008-12-19T13:29:19.127 に答える
1

では、なぜ使用しないのですか

static <T> T[] buildArray(Class<T> clazz){
ArrayList<T> l=new ArrayList<T>();
return l.toArray((T[]) java.lang.reflect.Array.newInstance(clazz, l.size()));
}

ノート。上記のコードを変更しました。

于 2008-12-19T14:44:51.190 に答える