7

ジェネリック型のクラスをクラスのコンストラクターに渡す必要があります。このクラスは、コンストラクターへの参照用のRoboSpice Android ライブラリーのSpiceRequestです。

この場合、ジェネリック型自体からアクセスできる場合、クラスがジェネリックのクラスをコンストラクターに渡す必要があるのは奇妙に思えますRESULT.classが、おそらく私はこれについて間違っています。とにかく、ライブラリのコードを変更するつもりはありませんが、 のジェネリック型にジェネリック型を使用する必要がありSpiceRequestますMap<String, ? extends Object>。これが私のコードです:

SpiceRequest<Map<String, ? extends Object>> request =
        new SpiceRequest<Map<String, ? extends Object>>(???) {
            ...
        };

そして、SpiceRequestコンストラクターの署名:

public SpiceRequest(final Class<RESULT> clazz) {
    ...
}

為に ???Map.class私はコンパイラエラーで試しました:The constructor SpiceRequest<Map<String,? extends Object>>(Class<Map>) is undefined.

Map<String, ? extends Object>.classエラーが発生します: Syntax error on tokens, PrimitiveType expected instead、具体的には下線が引かれ? extends Objectます。と同じエラーも出ますMap.class

またMap.<String, ? extends Object>class、同じコンパイラエラーも発生します。

ジェネリック クラスを取得する正しい方法は何Class<Map<String, ? extends Object>>ですか?

4

4 に答える 4

5

具体的なパラメーター化された型またはワイルドカードのパラメーター化された型のクラス リテラルはありません。Angelika Langerのジェネリックチュートリアルから:

ワイルドカードでパラメーター化された型は、型消去と呼ばれるプロセスでバイト コードに変換されるときに型引数を失います。型消去の副作用として、ジェネリック型のすべてのインスタンス化は、同じ実行時表現、つまり対応する生の型の表現を共有します。つまり、パラメータ化された型には、独自の型表現がありません。したがって、 、 、 などのクラス リテラルを作成しても意味がありません。List<?>.classそのようなオブジェクトは存在しないからです。生の型だけが、その実行時の型を表すオブジェクトを持ちます。と呼ばれます。List<? extends Number>.classList<Long>.classClassListClassList.class

同じ理由で、具体的なパラメーター化された型のクラス リテラルはありません。簡単に言えば、型消去です。

あなたの目的のために、クラスリテラルのチェックされていないキャストを行うだけで済みます。

Class<Map<String, ?>> c = (Class<Map<String, ?>>)(Class<?>)Map.class;

toClass<?>からの直接変換は不正であるため、ダブル キャスト スルーが必要であることに注意してください。Class<Map>Class<Map<String, ?>>

于 2013-01-19T22:50:55.633 に答える
4

この問題は、RoboSpice自体には実際には関係していませんが、Java構文の制限に関係しています。Javaでパラメーター化されたジェネリック型のクラス/型を取得するために使用できるリテラルはありません。

あなたが次のようなことをしたい場合

public class ListTweetRequest extends SpiceRequest<List<Tweet>> {

   public ListTweetRequest(Object cacheKey ) {
       super( <Here is the problem>, cacheKey );
   }
}

その場合、クラスList<Tweet>.classを親コンストラクターに渡すことはできません。ジェネリックは型消去を使用して実現されList<Tweet>.class、Javaでは実際の意味がないため、これは実際にはJavaの制限です。

最善かつ最もクリーンな回避策は、次のような中間タイプを使用することです。

public class ListTweet extends List<Tweet> {
}

public class ListTweetRequest extends SpiceRequest<ListTweet> {

   public ListTweetRequest(Object cacheKey ) {
       super( ListTweet.class, cacheKey );
   }
}

これには、 SpiceRequestのコンストラクターに渡すことができる実際の型を提供するという利点があります。ただし、難読化には注意してください。そのような場合、proguardはListTweetクラスを削除しようとします。難読化から明示的に保持する必要があります。

于 2013-01-20T07:37:09.003 に答える
0

私もその問題を抱えており、@Snicolasが言っているような解決策を見つけました。

次の robospice-sample-retrofit の例をご覧ください。

https://github.com/octo-online/RoboSpice-samples/blob/release/robospice-sample-retrofit/src/com/octo/android/robospice/sample/retrofit/network/SampleRetrofitSpiceRequest.java

実際には、生の List インターフェイスから継承するのではなく、ArrayList などのサブクラスから継承することをお勧めします。そうしないと、すべてのインターフェイス メソッドを実装する必要があります。

import java.util.ArrayList;

public class Contributor {
    public String login;
    public int contributions;

    @SuppressWarnings("serial")
    public static class List extends ArrayList<Contributor> {
    }
}
于 2014-08-17T13:45:22.197 に答える
0

いつも消去で推測しているのですが、Map.classで呼び出すだけにしてみましたか?

于 2013-01-19T21:59:08.550 に答える