获取类集合上元素的类型信息

时间:2010-05-28 23:18:32

标签: java generics reflection

我想获得对Collection中保存的Object类型的访问权限。下面是我可能想要这样做的时间和原因的简化示例。这甚至可能吗?

List<Address> addressList = new LinkedList<Address>();

Main.addElement(addressList);

Class Main{
   public void addElement(Object inArgument){
      List<Object> argument = (List<Object>)inArgument;
      argument.add( /* WOULD LIKE TO CREATE A NEW OBJECT OF THE APPROPRIATE TYPE
                       HERE, IN THIS CASE, IT WOULD BE OF TYPE: "Address" */ );
   }
}

4 个答案:

答案 0 :(得分:5)

不,你不能用Java的泛型的当前实现来做到这一点。类型参数在编译时被“擦除”。

您可以通过反射确定方法参数和返回类型以及成员变量的类型参数信息,但在这种情况下无效。

作为一种实用的解决方法,大多数想要执行类似操作的API都会将Class实例作为第二个参数。例如:

public void addElement(Collection<T> c, Class<? extends T> clz) 
  throws Exception
{
  Constructor<? extends T> ctor = clz.getConstructor();
  T el = ctor.newInstance();
  c.add(el);
}

答案 1 :(得分:3)

使用当前方法的定义方式无法执行此操作,因为在运行时无法使用泛型详细信息。另一种方法是:

public <T> void addElement(List<T> inArgument, Class<? extends T> clazz){
   T t = clazz.newInstnace();
   inArgument.add(t);
   // exception handling omitted for brevity
}

然后你就像这样打电话给addElement

addElement(addressList, Address.class);

有关泛型类型和类型擦除的详细信息,请参阅JLS。简而言之,类型擦除对此行为负责:

Vector<String> x = new Vector<String>(); 
Vector<Integer> y = new Vector<Integer>(); 
boolean b = x.getClass() == y.getClass();

b==true中的结果。

答案 2 :(得分:0)

argument.add( null );

null是每种参考类型的值:P

但严重的是,我不知道你为什么要这样做。这意味着您的类型存在某种“默认”值,一般情况下类型不适用。

答案 3 :(得分:0)

我不确定我理解你的问题,但我认为“超级”关键字在这里可能很有用。

List<Address> addressList = new LinkedList<Address>();
List<Object> stuffToSeeInWashington = new LinkedList<Object>();

Main.addWhiteHouse(addressList);
Main.addWhiteHouse(stuffToSeeInWashington);

Class Main{
   public void addWhiteHouse(List<? super Address> argument){
      Address whiteHouse = new Address("1600 Pennsylvania Ave");
      argument.add( whiteHouse ) ;
   }
}