2012-01-10 15 views
0

私はabstract class Abstr<T>と延長class Ext<T>を持っています。 Abstrを知っている必要があります。T拡張子が初期化されているため、そのタイプを返すことができます。これまでは、コンストラクタに型を与え、それを保存するためにスーパーコンストラクタを呼び出すことでこれを行ってきました。しかし、これは反射でもうまくいくはずです。私が言ったこれまでのように:反射を利用しJavaのスーパークラスのコンストラクタに拡張汎用クラスの汎用タイプを取得しますか?

public abstract class Abstr<T> { 

    private Class<T> type; 

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

} 

public class Ext<T> extends Abstr<T> { 

    public Ext(Class<T> _class) { 
     super(_class); 
    } 

} 

public void someMethod() { 
    Ext<String> ext = new Ext<String>(String.class); 
} 

は拡張デフォルトのコンストラクタは、その後の呼び出しコンストラクタの種類を保存する必要があります抽象クラスのデフォルトコンストラクタを呼び出すよう任意のコンストラクタを呼び出すの私を取り除く必要があります。

public Abstr() {  
    this.type = (Class<D>) this.getClass().getTheTypeParameter(); // something along these lines 
} 

ありがとう!

+0

質問は?単にそれを試してみるのはなぜですか? – duffymo

+0

質問は、反射でそれを行う方法です..コードのいくつかの行でなければなりません。 – Pete

+0

@Pete: 'String.class'型を' Ext'に実際に渡すことなくそれを行うことはできません。 –

答えて

1

あなたは、コンストラクタでClass isntanceを渡すしかない(または他の方法で)。 type erasureのためにのTを取得することはできません。これは基本的にはTがコンパイル時にのみ実行時に使用できないという事実になります。

1

これは、ある種の方法でnew Ext<String>()があるだけなので、タイプの反射データがないため、これは必ずしも機能しない場合があります。

したがって、Ext<String> ext = new Ext<String>(String.class);は、実行時に型情報を失い(効果的に消去)、Ext ext = new Ext(String.class);になります。

private Ext<String> stringExtなどのフィールドやStringExt extends Ext<String>などの具象サブクラスの場合は、取得できる反射データがあります。ここで

を使用すると、反射具象サブクラスのためのデータを取得するために使用できるいくつかのソースとの短い記事だ(そしておそらくフィールドのために、私はそれをテストしていない):私が言ったように、私たちが使っている http://www.artima.com/weblogs/viewpost.jsp?thread=208860

具体的なサブクラスの型パラメータを取得するためのコードの調整版です。

は、だから我々はこのようなものを持っている:あなたは本当に

public Class<T> getType() 

に似Abstrのメソッドが必要な場合は

class AbstractDAO<T entityType> { 
    protected Class<?> entityClass; 

    protected AbstractDAO() { 
    //ReflectionUtil is our adjusted version of code in the link above 
    entityClass = ReflectionUtil.getTypeArguments(AbstractDAO.class, getClass()).get(0); 
    } 
} 

//Here entityClass is User.class 
class UserDAO extends AbstractDAO<User> { ... } 
3

generic以外のクラスがある場合のみ動作します。答えはそこにあるが、それはそれを引用し、私は、コードを盗んでいたかのように感じるしないようにあまりにも長いです - 例では、さらに読書のために

class Trick<T> { 
    T t; 
} 

public class GenericTest { 
    public static void main(String[] args) { 
     Trick<Set<String>> trick = new Trick<Set<String>>() { 
     }; 

     // Prints "class org.acm.afilippov.GenericTest$1" 
     System.out.println(trick.getClass()); 
     // Prints "org.acm.afilippov.Trick<java.util.Set<java.lang.String>>" 
     System.out.println(trick.getClass().getGenericSuperclass()); 
    } 
} 

Reflecting genericsのチュートリアルを参照することでしょう。だからそこに読んでください:)

+0

それはかなり奇妙です。実行時に型境界を取得する信頼できる方法のようには見えません。まだ興味深いですが、 –

+0

@ LukasEderさらに悪い:それは*実行していない*ランタイムです。あなたが読むことのできる型の境界はコンパイル時に設定されます。内側のクラスは 'GenericTest $ 1'です:コードに明示的に定義された具体的で非ジェネリックなクラスです。したがって、 "実行時に"読みたいタイプパラメータの場合は、コンパイル時にクラスを定義する必要があります。 – alf

+0

それらのクレイジージェネリック... ;-) –

1

Abstrの一般的なタイプはTです。これはすべてあなたが反射を介して得ることができます。

コードをシンプルにしたい場合は、書くことができます。

public class Ext<T> extends Abstr<T> { 
    protected Ext(Class<T> _class) { 
     super(_class); 
    } 

    public static <T> Ext<T> of(Class<T> _class) { return new Exit<T>(_class); } 
} 

Ext<String> ext = Ext.of(String.class); 
関連する問題