2011-07-08 10 views
22

ジェネリックを使用しているときにJavaで小さな問題があります。私はクラスA持っている:Aの方法でジェネリッククラスのジェネリックパラメータの型名を取得

public class A<T> 

を、私はTの型名を取得する必要があります。 を使用して文字列sを見つける方法はありますか?

(私がA<String> temp = new A<String>();を作成すると、java.lang.Stringを取得できるようにしたい - 私のメソッドの1つがList<T>を返さなければならないため、汎用性を使用する必要があります)。

これはかなり簡単ですが、私はそれを行う方法がわかりません。

ご協力いただきありがとうございます。 A<String>のインスタンスはTの種類を知りません- 型消去のため

+2

この質問を見るhttp://stackoverflow.com/questions/3403909/get-generic-type-of-class-at-runtime –

答えて

34

あなたは、一般的にこれを行うことはできません。その後

public class A<T> 
{ 
    private final Class<T> clazz; 

    public A<T>(Class<T> clazz) 
    { 
     this.clazz = clazz; 
    } 

    // Use clazz in here 
} 

:あなたがそれを必要とする場合、一つの方法は、リテラルのタイプを使用することです

A<String> x = new A<String>(String.class); 

それは醜いですが、それは型消去が何をするかだ:(

代替が使用することですこれはGuiceのTypeLiteralのようなものです。スーパークラスを指定するために使用された型引数が消去されないので、これは機能します:

を取得することにより、あなたは最終的に戻って Stringに得ることができるので、

aは今、サブクラスA<String>を指します。それはかなり恐ろしいです。

0

Javaのジェネリックは消去によって実装されるため、実行時にジェネリックコレクションを作成するために使用された "タイプ"の名前を取得することはできません。また、エレメントがどのタイプに属しているかを調べるだけではどうですか?

+0

私はTのインスタンスが最初にないので、実際にはできません。オブジェクトはosgiサービス・リスナーを実装しており、インターフェース名でバンドル・メッセージをフィルタリングしたいとします。それ以降はインスタンスを取得します。 – ThR37

9

短い答え:不可能。

少し長い答え:コードがコンパイルされると、型パラメータは破棄されます。 こうして、Javaはあなたが設定したものを知ることができません。あなたは、しかし、あなたのオブジェクトへの質問でクラスを渡し、それを操作することができ :確かに

public class A<T> { 
    private final clazz; 

    A(Class<T> clazz){ 
    this.clazz = clazz; 
    } 
... 
} 
+0

これは確かに答えになるはずです。 *イレージャー(これは私がよく聞いた言葉ですが、必ずしも完全には深く分析されたことはありません)のため、ジェネリックパラメーターを "密輸入"の余分なパラメーターとして使用することはできません。代わりに、通常のパラメータを使用します。この情報が決して得られないことは奇妙に思えますが、これが設計上の選択か不可避なのかはっきりしていません... –

5

これには、long型の引数は、Aのサブクラスを介して指定されたとしても可能である:

public class B extends A<String> {} 

Class<?> typeArg = TypeResolver.resolveRawArgument(A.class, B.class); 
assert typeArg == String.class; 

TypeResolverはTypeToolsから入手できます。

+0

私は本当にこれが答えを提供し、コードを手に入れたいと思っていました。しかし、私はOPがやろうとしていることをすることができませんでした。つまり、実際にサブクラスを作ることなく、オンザフライで作成されたAのインスタンスからジェネリックパラメータを取得します。私はこれが不可能だと推測します... –

16

サブクラスからジェネリックの名前を取得できます。この例を参照してください。 我々はこのような親クラスを定義します。

public class GetTypeParent<T> { 

    protected String getGenericName() 
    { 
     return ((Class<T>) ((ParameterizedType) getClass() 
       .getGenericSuperclass()).getActualTypeArguments()[0]).getTypeName(); 
    } 
} 

私たちは、この方法では、その子クラスを定義します。

public class GetTypeChild extends GetTypeParent<String> { 
    public static void main(String[] args) { 
     GetTypeChild getTypeChild = new GetTypeChild(); 
     System.out.println(getTypeChild.getGenericName()); 
    } 
} 

あなたは私は、mainメソッドで、または任意のインスタンスメソッドでそれを見ることができますジェネリック型の名前を取得することができます。この場合、メインはjava.lang.Stringを出力します。

+1

...サブクラスの名前があればそれを取得します。ニース! –

+1

これは確かに賢いようです...しかし、あなたは '' String''をタイプするために ''ハードコーディング ''しなければなりません。ジェネリックパラメータの価値を見つけようとすることについて疑問ではありませんか? –

+0

私はこれが役立つとは思わない。子クラスは既にハードコードされているため、型を認識しています:String。親のメソッドを呼び出すのは便利ではありません。残念ながら、それは便利なユースケースではなく、OPが@mikerodent –

1

あなたはそれがジェネリック型を定義し、親クラスのしているサブクラスでそれをやっている場合は、これが私のために働いていたものです:私は#getClass()の代わり#toString()でそれを行うことができなかった理由を

// get generic type class name 
String name = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].toString(); 

// then when you've got the name, you can make the Class<T> object 
Class.forName(name.replace("class ", "")) 

理由最初のスナップでは、いつも私が役に立たない「クラス」クラスを取得していたということです。

https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/reflect/TypeUtils.html

上記の質問から簡単な例:

TypeUtils.getTypeArguments(temp.getClass(), A.class).get(A.class.getTypeParameters()[0]) 

免責事項:私はしようとしませんでした

0

通常の場合と同様に、ApacheはTypeUtilsと、この1のためのソリューションを持っていますこれを最初に構築しましたが、過去に同様の方法でこのユーティリティを使用しました。

+0

Apache Commonsの大ファンは、 'TypeUtils'について聞いたことがないので、ありがたいです...しかし、これは現在私にとってはうまくいきません:' A.class'は "型パラメータAに対して不正なクラスリテラル"というエラーを出しています。 'TypeUtils'でいくつかの探検/実験をやろうとしています... –

+0

@mikeげっ歯類これは、階層化の階層にある複数のクラスで、階層構造を通って動いている間にタイプ数を変えて使用したときに働いていました。動作しなかった例がありますか? – Hazok

+0

後で、いいえ、これを動作させることができませんでした。最初に 'ParameterizedType'を得る方法がわかりません。ジョナサンの答えとエンリコ・ゲランのことも見ています。しかしインスタンス(OPの質問)からジェネリック型を直接得ることは、たとえApacheにとっても不可能と思われます。あなたが私にどのように表示することができない限り! –

関連する問題