【问题标题】:Convert java.lang.reflect.Type to Class<T> clazz将 java.lang.reflect.Type 转换为 Class<T> clazz
【发布时间】:2020-04-14 18:22:14
【问题描述】:

如何将java.lang.reflect.Type 转换为Class&lt;T&gt; clazz

如果我有一个方法作为 next 其参数为 Class&lt;T&gt;:

public void oneMethod(Class<T> clazz) {     
    //Impl
}

然后是另一个方法,它的参数为java.lang.reflect.Type,它调用oneMethod(Class&lt;T&gt; clazz),为此我需要将java.lang.reflect.Type type 转换为Class&lt;T&gt;

public void someMehtod(java.lang.reflect.Type type) {
   // I want to pass type arg to other method converted in Class<T>
   otherMethod(¿How to convert java.lang.reflect.Type to Class<T>?);
}

有可能吗?

【问题讨论】:

    标签: java generics


    【解决方案1】:

    您必须确保typeClass 的一个实例,然后再进行转换。

    if (type instanceof Class) {
      Class<?> clazz = (Class<?>) type;
      otherMethod(clazz);
    }
    

    当然,您还必须处理它不是Class的情况。

    【讨论】:

      【解决方案2】:

      如果你愿意使用图书馆,你可以使用com.google.guava:guava:12+

      Class<?> clazz = com.google.common.reflect.TypeToken.of(type).getRawType();
      

      或者你也可以使用com.fasterxml.jackson.core:jackson-databind:2.8.x:

      Class<?> clazz = com.fasterxml.jackson.databind.type.TypeFactory.rawClass(type);
      

      这会正确处理所有情况,您将获得您的类型的类型擦除类。

      【讨论】:

        【解决方案3】:

        在运行时使用泛型类型在 Java 中有点棘手。我认为这是您问题的根本原因。

        1) 为了确保运行时的泛型,我们这样做:

        class MyClass<E> {}
        

        然后:

        MyClass<TargetType> genericAwaredMyClassInctance = new MyClass<TargetType>(){};
        

        请注意最后的{}。这意味着 MyClass 的匿名扩展。这是一个重要的细微差别。

        2) 让我们改进 MyClass 以便能够在运行时提取类型。

        class MyClass<E> {
        
            @SuppressWarnings("unchecked")
            protected Class<E> getGenericClass() throws ClassNotFoundException {
                Type mySuperclass = getClass().getGenericSuperclass();
                Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
                String className = tType.getTypeName();
        
                return (Class<E>) Class.forName(className);
            }
        
        }
        

        最后,像这样使用它:

        MyClass<TargetType> genericAwaredMyClassInctance = new MyClass<TargetType>(){};
        
        assert(genericAwaredMyClassInctance.getGenericClass() == TargetType.class)
        

        【讨论】:

          【解决方案4】:

          Andy Turner 的回答是正确的,但是如果您需要从类型参数中检索一个类,这是一个完整的示例:

          private static class MyClass extends ArrayList<Integer> {
          }
          
          public static void main(String[] args) {
          
              ParameterizedType arrayListWithParamType
                      = (ParameterizedType) MyClass.class.getGenericSuperclass();
          
              Type integerType = arrayListWithParamType.getActualTypeArguments()[0];
          
              Class<?> integerClass = (Class<?>) integerType;
          
              System.out.println(integerClass == Integer.class);
          }
          

          【讨论】:

            【解决方案5】:

            如果Type 不是Class,那就太奇怪了...Type 的 Javadoc 说

            所有已知的实现类: 类

            因此,除非您有使用非 ClassTypes 的特殊库,否则您可以简单地转换 - 但您必须为可能的 ClassCastException 做好准备。 注意:Java 使用未记录的 Type 实现来表示泛型,见下文。

            你可以明确地处理它或不处理它,因为它是一个未经检查的异常:

            显式方式:

            try {
                Class<?> clazz = (Class<?>) type;
            }
            catch (ClassCastException ex) {
                // process exception
            }
            

            隐式方式:

            Class<?> clazz = (Class<?>) type;
            

            但是当前的方法可能会抛出...


            根据@Andy Turner 的评论进行编辑:

            注意:Type type = new ArrayList&lt;String&gt;().getClass().getGenericSuperclass(); 产生的东西是类型而不是类。这个是ParameterizedType,所以你可以使用getRawType()方法找到实际的类,但其他的可能存在。

            【讨论】:

            • 例如Type type = new ArrayList&lt;String&gt;().getClass().getGenericSuperclass(); 产生的东西是 Type 但不是 ClassIdeone demo.
            • @AndyTurner:你说得对,它是一个内部未记录的类......你肯定猜到它实现了ParameterizedType,然后使用getRawType() 来找到一个真正的类。
            • @SergeBallesta:这就是重点。 Type 可以是Class 的实例,也可以是ParameterizedTypeTypeVariableWildcardTypeGenericArrayType 的实例。后4个是接口;实现类不相关。
            • 别忘了:All Known Subinterfaces: GenericArrayType, ParameterizedType, TypeVariable&lt;D&gt;, WildcardType 也别忘了你可以在任何地方匿名实现一个接口——所以实际上可能有很多类实现了这些接口。在实践中,类型的其他实现是通过调用例如获得的。 field.getGenericType().
            【解决方案6】:

            你是这个意思吗?

            public <T extends Type> void oneMethod(T clazz) {
            
            }
            
            public void someMethod(Type type) {
                oneMethod(type);
            }
            

            【讨论】:

            • 您只是将问题移到方法内部
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-01-03
            • 2016-12-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多