web-dev-qa-db-ja.com

既知のタイプのクラスリテラルを作成する方法:Class <List <String >>

以下を取ります:

_public Class<List<String>> getObjectType() {
    // what can I return here?
}
_

ジェネリックを満たしコンパイルするこのメソッドからどのクラスリテラル式を返すことができますか? _List.class_はコンパイルされず、_List.<String>class_もコンパイルされません。

「なぜ」と思っているのであれば、Springの_FactoryBean<List<String>>_の実装を書いています。これにはClass<List<String>> getObjectType()を実装する必要があります。ただし、これはnotSpringの質問です。

編集:私の悲嘆の叫びは、SpringSourceにいる力によって聞かれたので、Spring 3.0.1はgetObjectType()の戻り値の型を_Class<?>_に変更します。問題をきちんと回避できます。

56
skaffman

このように、いつでも必要なものにキャストできます

return (Class<List<String>>) new ArrayList<String>().getClass();

または

return (Class<List<String>>) Collections.<String>emptyList().getClass();

しかし、それはあなたが望んでいることではないと思います。まあ、それは警告付きで動作しますが、それは正確に「美しい」ではありません。

私はこれを見つけました

ワイルドカードのパラメーター化された型にクラスリテラルがないのはなぜですか?

ワイルドカードのパラメーター化された型には正確なランタイム型表現がないためです。

キャストが唯一の方法かもしれません。

43
Bozho

コンストラクトClass<List<String>>を使用しないでください。これは無意味で、Java(ただしそうではない))で警告を生成する必要があります。クラスインスタンスは常に生の型を表すため、Class<List>;を持つことができます。 List<String>のような具体化されたジェネリック型を表すものには、Guiceが使用するような「スーパータイプトークン」が必要です。

http://google-guice.googlecode.com/git/javadoc/com/google/inject/TypeLiteral.html

15

Class<List<String>>の存在は本質的に危険です。その理由は次のとおりです。

// This statement generates a warning - for a reason...
Class<List<String>> unsafeListClass = (Class<List<String>>) (Class<?>) List.class;

List<Integer> integerList = new ArrayList<Integer>(); // Ok
integerList.add(42); // Ok

System.out.println(unsafeListClass.isInstance(integerList)); // Prints "true".
List<String> stringList =
   unsafeListClass.cast(integerList); // Succeeds, with no warning!
stringList.add("Hello, World!"); // Also succeeds with no warning

for (int x: integerList) {
    // Compiles without warning, but throws ClassCastException at runtime
    System.out.println(100-x);
}
7
finnw

Springframework.orgで このリンク が見つかりました。

例えば。

List<String> myList = new ArrayList<String>();
return (Class<List<String>>)myList.getClass();
6
JRL

このメソッドは次のように実装できます。

public Class<List<String>> getObjectType() {
    return (Class<List<String>>) ((Class)List.class);
}
5
Saeed Zarinfam

Sunフォーラムでこの議論をチェックしてください。

http://forums.Sun.com/thread.jspa?threadID=5253007

また、「スーパータイプトークン」を使用して回避策を説明する参照ブログ投稿:

http://gafter.blogspot.com/2006/12/super-type-tokens.html

2

クラスリテラルはClass.forName(...)にコンパイルされ、実行時に発生するため、一般的な情報は残っていないため、これが可能かどうかはわかりません。

1
perdian

次のアプローチには問題があります。

> public Class<List<String>> getModelType() {
>   return (Class<List<String>>) new ArrayList<String>().getClass();
> }

例えばオブジェクトがタイプを言うかどうかをテストしたい場合

org.Eclipse.emf.common.util.BasicEList<String> 

タイプです

List<String> 

前述のgetModelType()アプローチの結果に基づいて、たとえば:

BasicEList<String> fromObject = ...;
if (getModelType().isAssignableFrom(fromObject.getClass())) {
    transferFromModelToUi(getModelType().cast(fromObject));
}

これはfalseになりますが、両方のオブジェクトがインターフェイスリストを実装するため、trueになります(getModelType()はArrayListではなくList型のClassオブジェクトを返すため)。

私のために働いたアプローチはここにあります(少し面倒ですが、上記の例では正しい結果につながりますが、静的イニシャライザに移動できます):

public Class<List<String>> getModelType() {
    Class<?> arrayListClass = new ArrayList<String>().getClass();
    Class<?>[] interfaces = arrayListClass.getInterfaces();
    int index = 0;
    for (int i = 0; i < interfaces.length; i++) {
        if (interfaces[i].equals(List.class)) {
            index = i;
            break;
        }
    }
    return (Class<List<String>>) interfaces[index];
}
0
Lukas Z.

よくわかりませんが、次の質問はあなたに関連があるかもしれません...

Javaジェネリック型パラメーターとそれらの型の操作

0
Yaneeve

これはどうですか:

public class TestMain {
    public static void main(String[] args) throws Exception {
        Type type = TestMain.class.getMethod("dummy").getGenericReturnType();
        System.out.println("type = " + type);
    }

    public List<Integer> dummy() {return null;}
}

これは印刷します:

type = Java.util.List<Java.lang.Integer>
0
mazi