2012-10-29 84 views
2

如何创建一个泛型类,它从创建/注入此泛型类时放置的泛型类型参数中获取类类型? 我的目标是指定例如MyGeneric<User>,然后通用类应该能够在所有方法调用中使用User类。而不必在附加的泛型构造函数中明确提供User.class仅通过类型参数创建泛型类?

喜欢的东西:

class MyGeneric<T> { 
    public MyGeneric() { 
     someService.create(Class<T>, someString); 
    } 
} 

class Usage { 
    @Inject 
    MyGeneric<User> myuser; 
} 

这是怎么propertly做了什么?

+0

为什么?这不会允许MyGeneric使用T的方法。MyGeneric只能使用T的上界方法。 – ignis

回答

0

你可以做的是在超类中编写实例化代码,然后对每个特定的泛型类型进行扩展(在子类中需要很少或没有代码,但是子类是必需的,因为它们是避免类型的唯一方法擦除):

abstract class MyGeneric<T> { 

    private T instance; 

    public MyGeneric(String str) { 
     // grab the actual class represented by 'T' 
     // this only works for subclasses of MyGeneric<T>, not for MyGeneric itself ! 
     Class<T> genericType = (Class<T>) ((ParameterizedType)getClass().getGenericSuperclass()) 
       .getActualTypeArguments()[0]; 
     try { 
      // instantiate that class with the provided parameter 
      instance = genericType.getConstructor(String.class).newInstance(str); 
     } catch (Exception e) { 
      throw new IllegalArgumentException(e); 
     } 
    } 
} 

class MyUser extends MyGeneric<User> { 
    public MyUser() { 
     // provide the string to use for instantiating users... 
     super("userStr"); 
    } 
} 

class User { /*...*/ } 

编辑:由通用类abstract强制子类的用法。

它也可以用匿名类等一起使用:

new MyGeneric<User>("..string...") {}

我觉得这是最接近您最初的目标,你可以得到...

2

由于运行时间type erasure,无法执行此操作。

通常的方法是(如你所说)将Class<T>的实例 - 称为type token - 传递给构造函数。鉴于你的代码模式,你坚持使用这种方法。

0

这是有点棘手,但与例如TypeLiteral从吉斯,你可以做这样的事情:

public class ReiHashMap<K,V> extends HashMap<K,V> { 

    private final TypeLiteral<K> keyTL; 

    public ReiHashMap(TypeLit<K> keyTL) { 
     this.keyTL = keyTL; 
    } 

    @Override 
    public V get(Object o) { 
     if (!keyTL.getRawType().isAssignableFrom(o.getClass())) { 
      throw new IllegalArgumentException("object " + o + " (class "+ o.getClass() +")ist not of type " + keyTL); 
     } 
     return super.get(o); 
    } 
    ... 

这是一个扩展,可以检查在运行时获取的参数的类型包含HashMap。