26

同様の質問を見たことがありますが、あまり役に立ちませんでした。

たとえば、私はこの汎用クラスを持っています:

public class ContainerTest<T>
{

    public void doSomething()
    {
        //I want here to determinate the Class of the type argument (In this case String)
    }
}

およびこのコンテナ クラスを使用する別のクラス

public class TestCase
{

    private ContainerTest<String> containerTest;

    public void someMethod()
    {
        containerTest.doSomething();
    }
}

ContainerTestクラスに明示的な型変数/フィールドまたはコンストラクターを持たずに、メソッドdoSomething()で型引数のクラスを決定することは可能ですか?

更新: ContainerTest クラスのフォーマットを変更

4

7 に答える 7

17

唯一の方法は、クラスをインスタンス変数に格納し、それをコンストラクターの引数として要求することです。

public class ContainerTest<T>
{
    private Class<T> tClass;
    public ContainerTest(Class<T> tClass) {
        this.tCLass = tClass;
    }

    public void doSomething()
    {
        //access tClass here
    }
}
于 2013-02-26T08:49:41.227 に答える
10

リフレクションの方法に興味がある場合は、この素晴らしい記事で部分的な解決策を見つけました: http://www.artima.com/weblogs/viewpost.jsp?thread=208860

つまり、java.lang.Class.getGenericSuperclass()andjava.lang.reflect.ParameterizedType.getActualTypeArguments()メソッドを使用できますが、一部の親スーパー クラスをサブクラス化する必要があります。

次のスニペットは、スーパークラスを直接拡張するクラスで機能しますAbstractUserType。より一般的な解決策については、参照記事を参照してください。

import java.lang.reflect.ParameterizedType;


public class AbstractUserType<T> {

    public Class<T> returnedClass() {
        ParameterizedType parameterizedType = (ParameterizedType) getClass()
                .getGenericSuperclass();

        @SuppressWarnings("unchecked")
        Class<T> ret = (Class<T>) parameterizedType.getActualTypeArguments()[0];

        return ret;
    }

    public static void main(String[] args) {
        AbstractUserType<String> myVar = new AbstractUserType<String>() {};

        System.err.println(myVar.returnedClass());
    }

}
于 2013-08-10T12:41:16.260 に答える
7

クラス内からジェネリック型引数を取得する「クリーンな」方法はありません。代わりに、一般的なパターンは、ジェネリック型のクラスをコンストラクターに渡し、java.util.EnumMap実装で行われるように、それを内部プロパティとして保持することです。

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/EnumMap.html http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk /6-b14/java/util/EnumMap.java

public class ContainerTest<T> {

    Class<T> type;
    T t;

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

    public void setT(T t) {
        this.t = t;
    }

    public T getT() {
        return t;
    }

    public void doSomething() {
        //There you can use "type" property.
    }
}
于 2013-02-26T08:50:08.193 に答える
4

いいえ。型消去のために不可能です(型パラメーターはオブジェクト+型キャストとしてコンパイルされます)。実行時にタイプを本当に知る/強制する必要がある場合は、オブジェクトClassへの参照を保存できます。

public class ContainerTest<T> {
   private final Class<T> klass;
   private final List<T> list = new ArrayList<T>();

   ContainerTest(Class<T> klass) {
     this.klass = klass;
   }

   Class<T> getElementClass() {
     return klass;
   }

   void add(T t) {
      //klass.cast forces a runtime cast operation
      list.add(klass.cast(t));
   }
}

使用する:

ContainerTest<String> c = new ContainerTest<>(String.class);
于 2013-02-26T08:50:38.277 に答える
2

Guava を使用して型パラメーターの実行時型を取得する方法がありますTypeToken。ソリューションの欠点は、 のインスタンスが必要になるたびに匿名サブクラスを作成する必要があることですContainer

class Container<T> {

    TypeToken<T> tokenOfContainedType = new TypeToken<T>(getClass()) {};

    public Type getContainedType() {
        return tokenOfContainedType.getType();
    }
}

class TestCase {

    // note that containerTest is not a simple instance of Container,
    // an anonymous subclass is created
    private Container<String> containerTest = new Container<String>() {};

    @Test
    public void test() {
        Assert.assertEquals(String.class, containerTest.getContainedType());
    }
}

TypeTokenこのソリューションの鍵は、上記のコードで使用されている のコンストラクターのJavaDoc で説明されています。

クライアントは、空の匿名サブクラスを作成します。そうすることで、匿名クラスの型階層に型パラメーターが埋め込まれ、消去されても実行時に再構成できるようになります。

于 2013-02-26T10:26:43.840 に答える
1

の値を知るには、TContainerTest をサブクラス化して型定義に取り込む必要があります。

class MyStringClass extends ContainerTest<String> {}

必要に応じて、匿名クラスでこれを行うこともできます。

ContainerTest<String> myStringClass = new ContainerTest<String>{}();

次に、T の値を解決するために、TypeToolsを使用できます。

Class<?> stringType = TypeResolver.resolveRawArgument(ContainerTest.class, myStringClass.getClass());
assert stringType == String.class;
于 2013-10-26T02:40:52.290 に答える
-1

あなたがこのように定義できるなら

public class ContainerTest<T>
{

    public void doSomething(T clazz)
    {

    }
}

その後、それは可能です

于 2013-02-26T08:51:26.793 に答える