67

次のようにします。

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

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

「なぜ」とお考えの場合は、Springの実装を作成しています。これには、の実装FactoryBean<List<String>>が必要ですClass<List<String>> getObjectType()。ただし、これは春の質問ではありません。

編集:私の哀れな叫びはSpringSourceにいる勢力によって聞かれたので、Spring 3.0.1ではreturnタイプがにgetObjectType()変更されClass<?>、問題をうまく回避できます。

4

9 に答える 9

56

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

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

また

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

しかし、私はそれがあなたが求めているものではないと思います。それは警告付きで機能しますが、正確には「美しい」わけではありません。

私はこれを見つけました

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

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

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

于 2010-01-06T11:13:15.613 に答える
15

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

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

于 2010-01-06T18:30:42.343 に答える
12

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

public Class<List<String>> getObjectType() {
    return (Class<List<String>>) ((Class)List.class);
}
于 2014-04-13T16:15:40.667 に答える
8

aの存在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);
}
于 2010-02-12T00:12:25.000 に答える
6

いくつかの洞察を与えるspringframework.orgでこのリンクを見つけました。

例えば

List<String> myList = new ArrayList<String>();
return (Class<List<String>>)myList.getClass();
于 2010-01-06T11:06:31.447 に答える
2

SUNフォーラムでこのディスカッションをチェックしてください。

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

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

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

于 2010-01-06T11:21:55.387 に答える
1

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

于 2010-01-06T11:08:36.573 に答える
0

これはどうですか:

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>
于 2013-05-09T09:11:52.853 に答える
0

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

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

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

これが私のために働いたアプローチです(少し面倒ですが、上記の例では正しい結果につながり、静的初期化子に移動できます):

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];
}
于 2014-03-28T07:54:20.497 に答える