2017-03-02 12 views
2

を拡張しなさい私は(ParameterizedType)getClass().getGenericSuperclass()を実行すると、私は、 はTになるこのクラスのジェネリック型をなしジェネリック型クラスから

public class RequestDataEditor<T> extends PropertyEditorSupport { 
    @Override 
    public void setAsText(String text) { 

     MyData<T> value; 

     try { 
      //(ParameterizedType)getClass().getGenericSuperclass() 

      value = JacksonUtil.parse(text, new TypeReference<MyData<T>>() { 
      }); 
     } catch (Exception e) { 
      value = null; 
     } 

     setValue(value); 
    } 
} 

のようなクラスを期待しているが、それはPropertyEditorSupportだし、キャストすることはできませんパラメータ化された型に;

私はextends PropertyEditorSupportを削除した場合、私は、ジェネリック型を得ることができます。(私はここでミスを犯した、間違っていることが判明した。)

我々からジェネリック型を取得するために(ParameterizedType)getClass().getGenericSuperclass()を使用することができない、ということらしいです親がジェネリック型を持たないクラス

したがって、RequestDataEditorのようなクラスでジェネリック型を取得するにはどうすればよいですか?

not duplicate with the questionの場合、(ParameterizedType)getClass().getGenericSuperclass()を使用した場合、何が違うか知りたいです。クラスには、ジェネリックタイプのスーパークラスがありません。

+0

ジェネリックはコンパイル時の安全チェックです。実行時に使用可能な型情報は含まれません。 – 4castle

+0

@ 4castleクラス 'RequestDataEditor'に親クラスがない場合はジェネリック型を取得できます – JackYe

+0

'extends PropertyEditorSupport'を削除すると、' getGenericSuperclass() 'は単に' class Object'を返します。テストするには[mcve]を入力してください。 – kennytm

答えて

2

が、それはPropertyEditorSupportだ、と は、ParameterizedTypeにキャストすることはできません。

型パラメータにアクセスする場合は、適切な反映方法はClass.getTypeParametersです。

// Test.java: 
class Generic<T> { 
} 

class Main { 

    public static void main(String[] args) { 

    final Generic<Integer> gint1 = new Generic<Integer>(); 

    System.err.println("gint1's type-parameter: " 
         + gint1.getClass().getTypeParameters()[0]); 
    } 
} 

あなたは上記のコードを実行した場合には、以下を得る:タイプパラメータは、実行時には使用できませんで、この情報ので、整数としてではなくTとして解決されていないことを

$ javac Test.java 
$ java Main 
gint1's type-parameter: T 

注意してください。

この情報へのアクセスが重要な場合は、2つのストレートフォワードオプションがあります。

A.オブジェクトが実際の型クラスへの参照が含まれています

class Generic<T> { 

    public final Class<T> type; 

    public Generic(Class<T> type) { 
     this.type = type; 
    } 

    public Class<T> type() { 
     return type; 
    } 
} 

class Main { 
    public static void main(String[] args) { 

     final Generic<Integer> gint2 = new Generic<>(Integer.class); 
     System.err.println("gint2's type-parameter: " + gint2.type().getSimpleName()); 
    } 
} 
// Output will be "gint2's type-parameter: Integer". 

B.あなたはその型パラメータのための具体的なクラスを与えるサブクラスを作成します。

import java.lang.reflect.*; 

class Generic<T> { 
} 

class IntegerGeneric extends Generic<Integer> { 
} 

class Main { 
    public static void main(String[] args) { 

     final Generic<Integer> gint3 = new IntegerGeneric(); 
     final Generic<Double> gint4 = new Generic<Double>() {}; 
     System.err.println("gint3's type-parameter: " 
      + ((ParameterizedType)gint3.getClass().getGenericSuperclass()).getActualTypeArguments()[0]); 
     System.err.println("gint4's type-parameter: " 
      + ((ParameterizedType)gint4.getClass().getGenericSuperclass()).getActualTypeArguments()[0]); 
    } 
} 
// Output: 
// gint3's type-parameter: class java.lang.Integer 
// gint4's type-parameter: class java.lang.Double 

お知らせgint4クラスはGeneric<Double>ではありませんが、コンストラクタに続いて{}のために拡張する匿名の内部クラスです...これは完全なclass DoubleGeneric ...宣言の代わりです。

これらの2つの選択肢のうち、A.とB.、A.一般的に反射に頼るのは避けるべきであるので好ましい。とりわけ、ランタイムエラーを隠す傾向が強く、コードを保守することはより困難です。

は、私はクラスで使用 (は、ParameterizedType)のgetClass()。getGenericSuperclassは() なしジェネリック型のスーパークラスを持っていたときに違うのかを知りたいです。

あなたはルックアップTypeドキュメント、このメソッドによって返された参照のクラス、それはそれも含めて、Java言語で利用可能なすべてのオブジェクト/データ型の「傘」スーパーインタフェースであることを示している場合基本的なスーパークラスを持たないクラスのために、それはそれを反映する型のサブクラスを返すと思います...

簡単な実験では、 getSuperclass()と同等です。

おそらく他の人がこれについてもっと情報に基づいた視点を与えることができますが、これは誤った名前になっている可能性があると思います... getSuperType()などの方が適切だと思います。おそらく当初は古いJavaバージョン(1.5?)のジェネリックのみをサポートしていましたが、最終的に他のデータ型をカバーするように拡張されましたが、これは私の歴史を見ずに私の野生の推測です。

+0

詳細な説明をいただきありがとうございます! – JackYe

2

(ParameterizedType)getClass()。getGenericSuperclass()は、現在のクラスのスーパークラスを取得します。これは一般的なクラスではありません。あなたはスーパークラスではなく、現在のクラスのジェネリック型を必要とします。あなたの例では、このデータは実行時にもう利用できないので、これは不可能です。可能な解決策は次のようになります。

public class RequestDataEditor<T> extends PropertyEditorSupport { 

    private final Class<T> genericType; 

    public RequestDataEditor(Class<T> genericType) { 
     this.genericType = genericType; 
    } 

    @Override 
    public void setAsText(String text, ) { 

     MyData<T> value; 

     try { 
      //use genericType here 

      value = JacksonUtil.parse(text, new TypeReference<MyData<T>>() { 
      }); 
     } catch (Exception e) { 
      value = null; 
     } 

     setValue(value); 
    } 
} 

私は、これはあなたが達成しようとするまさにではありません知っているが、それは(私の知る限りでは)あなたが得ることができる最も近いです。 。

私は(は、ParameterizedType)のgetClass()getGenericSuperclass()を実行すると、 はTであることを期待
+0

Thx。私が間違えました。あなたの答えは、 'getGenericSuperclass()'メソッドをより深く理解するのに役立ちます。 – JackYe

+0

ようこそ。あなたはあなたの問題を解決しましたか? – mahieus

関連する問題