如何获得通用类型参数? [英] How to get the Generic Type Parameter?

查看:103
本文介绍了如何获得通用类型参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简单地说:

  public static class MyClass< T> {
//如果没有必要,我不想保留T的一个实例。
//它不好,不整齐。

//或者,假设成员的形式如下:
ArrayList< T> mArrayList = new ArrayList< T>();
//获取泛型类型参数的问题仍然存在。
}

@Test
public final void test(){
MyClass< Integer> myObject = new MyClass< Integer>();
getParamType(myObject);
}

private static final< T> void getParamType(final MyClass< T> _myObject){
System.out.println(_myObject.getClass()。getTypeParameters()[0]); ()(T)new Object())。getClass()); // T
System.out.println // class java.lang.Object
}



如何让代码打印类java.lang.Integer



我知道很多stackoverflow线程正在询问(和回答)这个问题。但是他们无法解决这个问题。




  • 我不知道为什么有些人需要调用 getGenericSuperclass() - 因为在这个简单情况下没有继承。

  • 我不能将它转换为 ParameterizedType



    $ b $ p $ <$ c $>
  • $ c> System.out.println((ParameterizedType)_myObject.getClass());
    //编译错误:无法从Class< capture#11-of?扩展TreeTest2.MyClass> to ParameterizedType

    System.out.println((ParameterizedType)_myObject.getClass()。getGenericSuperclass());
    //运行时异常:java.lang.ClassCastException






    基于@ Thomas的指导,我发现了一种 解决方法 来获取类java.lang.Integer 匿名(它需要是匿名的)子类 MyClass< code

    ; T> 在测试代码中。 (这很奇怪,为什么它只支持子类?)

      @Test 
    public final void test() {
    MyClass< Integer> myObject = new MyClass< Integer>(){}; //匿名子类
    getParamType(myObject);

    $ / code>

    然后我们可以使用 getGenericSuperclass() code>方法来获取类型然后将其转换为 ParameterizedType ,之后使用 getActualTypeArguments()

      private static final< T> void getParamType(final MyClass< T> _myObject){
    System.out.println(((ParameterizedType)_myObject.getClass()。getGenericSuperclass())。getActualTypeArguments()[0]);
    }

    完美地打印类java.lang.Integer



    这是不太好,因为测试代码应该模拟实际情况,用户最有可能将不会继续创建无意义的子类。



    这种方法基于 TypeReference类。但我真的不知道如何使用它。我试过 class MyClass< T>扩展了TypeReference< T> 。但我仍然需要创建 MyClass< T> 的子类以使 TypeReference.getType()打印 class java.lang.Integer



    请帮忙,谢谢任何输入,因为最好的方法还没有出现。




    基于上述解决方法的进一步问题:为什么只有匿名子类有效?



      public static class SubMyClass< T>扩展MyClass< T> {} 

    @Test
    public final void test(){
    MyClass< Integer> myObject = new MyClass< Integer>(){}; //匿名子类
    getParamType(myObject); // class java.lang.Integer

    MyClass< Integer> mySubObject = new SubMyClass< Integer>(); //命名的子类
    getParamType(mySubObject); // T

    MyClass getParamType()不变。)

    解决方案

    因为Java故意无法做到这一点(类型擦除)。



    解决方法称为超级类型令牌。还有一些关于此的线索(如这一个那一个)。


    Simply:

    public static class MyClass<T> {
        // i don't want to keep an instance of T, if it is not necessary.
        // and it is not nice, not neat.
    
        // Or, let's say, the member are in the form of :
        ArrayList<T> mArrayList = new ArrayList<T>();
        // the problem of getting the generic type parameter is still present.
    }
    
    @Test
    public final void test() {
        MyClass<Integer> myObject = new MyClass<Integer>();
        getParamType( myObject );
    }
    
    private static final <T> void getParamType(final MyClass<T> _myObject) {
        System.out.println(_myObject.getClass().getTypeParameters()[0]);    // T
        System.out.println(((T) new Object()).getClass());                  // class java.lang.Object
    }
    

    How to let the code print class java.lang.Integer?

    i know quite a few of stackoverflow threads are asking (and answering) about this. Yet they couldn't solve this question.

    • i don't know why some need to call getGenericSuperclass() - as there is no inheritance involved in this simple case.
    • And i can't cast it to ParameterizedType as well.

    .

    System.out.println((ParameterizedType) _myObject.getClass());
    // Compile Error: Cannot cast from Class<capture#11-of ? extends TreeTest2.MyClass> to ParameterizedType
    
    System.out.println((ParameterizedType) _myObject.getClass().getGenericSuperclass());
    // Runtime Exception: java.lang.ClassCastException
    


    Based on @Thomas's guide, i have found a work-around way to get class java.lang.Integer.

    First, we create an anonymous (it need to be anonymous) sub-class of MyClass<T> in the testing code. (Which is weird. Why it only support sub-classes?)

    @Test
    public final void test() {
        MyClass<Integer> myObject = new MyClass<Integer>() {};  // Anonymous sub-class
        getParamType( myObject );
    }
    

    Then we can use the getGenericSuperclass() method to get a Type then cast it to ParameterizedType and afterwards uses getActualTypeArguments():

    private static final <T> void getParamType(final MyClass<T> _myObject) {
        System.out.println( ((ParameterizedType) _myObject.getClass().getGenericSuperclass()).getActualTypeArguments()[0] );
    }
    

    It perfectly prints class java.lang.Integer.

    This is not-so-good because the testing codes should simulate the actual situation, where users most likely won't keep creating meaningless sub-classes.

    This approach is based on the idea of the TypeReference class. But i don't really know how to use it. I have tried class MyClass<T> extends TypeReference<T>. But i still have to create sub-class of MyClass<T> to have TypeReference.getType() prints class java.lang.Integer.

    Please help, and thanks for any inputs, as the best approach is not here yet.


    A further question based on the above workaround: Why only anonymous sub-class works?

    public static class SubMyClass<T> extends MyClass<T>{}
    
    @Test
    public final void test() {
        MyClass<Integer> myObject = new MyClass<Integer>() {};  // Anonymous sub-class
        getParamType( myObject );               // class java.lang.Integer
    
        MyClass<Integer> mySubObject = new SubMyClass<Integer>();   // named sub-class
        getParamType( mySubObject );            // T
    }
    

    (MyClass and getParamType() unchanged.)

    解决方案

    This is sort of difficult, because Java deliberately can't do that ("type erasure").

    The work-around is called super type tokens. There are also some threads on SO about that (like this one or that one).

    这篇关于如何获得通用类型参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆