我有一个泛型类,Foo<T>。在Foo的一个方法中,我想获取T类型的类实例,但我无法调用T.class。

使用T.class绕过它的首选方法是什么?


当前回答

然而,有一个小漏洞:如果您将Foo类定义为抽象类。这意味着您必须将类实例化为:

Foo<MyType> myFoo = new Foo<MyType>(){};

(注意末端的双撑杆。)

现在,您可以在运行时检索T的类型:

Type mySuperclass = myFoo.getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];

然而,请注意,mySuperclass必须是实际定义T的最终类型的类定义的超类。

它也不是很优雅,但你必须决定你喜欢新的Foo<MyType>(){}还是新的Foo<MyType<(MyType.class);在您的代码中。


例如:

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.NoSuchElementException;

/**
 * Captures and silently ignores stack exceptions upon popping.
 */
public abstract class SilentStack<E> extends ArrayDeque<E> {
  public E pop() {
    try {
      return super.pop();
    }
    catch( NoSuchElementException nsee ) {
      return create();
    }
  }

  public E create() {
    try {
      Type sooper = getClass().getGenericSuperclass();
      Type t = ((ParameterizedType)sooper).getActualTypeArguments()[ 0 ];

      return (E)(Class.forName( t.toString() ).newInstance());
    }
    catch( Exception e ) {
      return null;
    }
  }
}

然后:

public class Main {
    // Note the braces...
    private Deque<String> stack = new SilentStack<String>(){};

    public static void main( String args[] ) {
      // Returns a new instance of String.
      String s = stack.pop();
      System.out.printf( "s = '%s'\n", s );
    }
}

其他回答

我在抽象泛型类中遇到了这个问题。在这种特殊情况下,解决方案更简单:

abstract class Foo<T> {
    abstract Class<T> getTClass();
    //...
}

以及随后的派生类:

class Bar extends Foo<Whatever> {
    @Override
    Class<T> getTClass() {
        return Whatever.class;
    }
}

很多人不知道这个把戏!事实上,我今天刚找到它!它就像一个梦!请查看以下示例:

public static void main(String[] args) {
    Date d=new Date();  //Or anything you want!
    printMethods(d);
}

public static <T> void printMethods(T t){
    Class<T> clazz= (Class<T>) t.getClass(); // There you go!
    for ( Method m : clazz.getMethods()){
        System.out.println( m.getName() );
    }
}

比其他人建议的类更好的方法是传入一个对象,该对象可以执行您对类所做的操作,例如创建一个新实例。

interface Factory<T> {
  T apply();
}

<T> void List<T> make10(Factory<T> factory) {
  List<T> result = new ArrayList<T>();
  for (int a = 0; a < 10; a++)
    result.add(factory.apply());
  return result;
}

class FooFactory<T> implements Factory<Foo<T>> {
  public Foo<T> apply() {
    return new Foo<T>();
  }
}

List<Foo<Integer>> foos = make10(new FooFactory<Integer>());
   public <T> T yourMethodSignature(Class<T> type) {

        // get some object and check the type match the given type
        Object result = ...            

        if (type.isAssignableFrom(result.getClass())) {
            return (T)result;
        } else {
            // handle the error
        }
   }

实际上,这是可能的(没有外部库!)

以下是我对这个问题的(丑陋但有效的)解决方案:

import java.lang.reflect.TypeVariable;


public static <T> Class<T> getGenericClass() {
    __<T> instance = new __<T>();
    TypeVariable<?>[] parameters = instance.getClass().getTypeParameters(); 

    return (Class<T>)parameters[0].getClass();
}

// Generic helper class which (only) provides type information. This avoids the
//   usage of a local variable of type T, which would have to be initialized.
private final class __<T> {
    private __() { }
}