Java通用类 – 确定types

如果我创build一个Java类是通用的,如:

public class Foo<T> 

一个人怎么能在内部决定这个阶级呢,结果是什么?

 public ???? Bar() { //if its type 1 // do this //if its type 2 // do this //if its type 3 // do this //if its type 4 // do this } 

我围绕着Java API进行了探索,并使用了reflection的东西,instanceof,getClass,.class等,但似乎无法使它们成为正面或反面。 我觉得我很亲密,只需要结合一些电话,但总是不足。

更具体地说,我试图确定这个类是否被实例化为3种可能的types之一。

我已经使用了一个类似的解决scheme,他在这里解释了几个项目,发现它非常有用。

http://blog.xebia.com/2009/02/07/acessing-generic-types-at-runtime-in-java/

它的主要用途如下:

  public Class returnedClass() { ParameterizedType parameterizedType = (ParameterizedType)getClass() .getGenericSuperclass(); return (Class) parameterizedType.getActualTypeArguments()[0]; } 

与.NET相比,Javagenerics通过一种称为“types擦除”的技术来实现。

这意味着编译器将在生成类文件时使用types信息,但不会将此信息传输到字节码。 如果您使用javap或类似工具查看已编译的类,您将发现List<String>是类文件中的简单ListObject ),就像在Java-5之前的代码一样。

访问通用列表的代码将被编译器“重写”,以包含必须在早期版本中编写的types。 实际上,一旦编译器完成,以下两个代码片段与字节代码透视图相同:

Java 5:

 List<String> stringList = new ArrayList<String>(); stringList.add("Hello World"); String hw = stringList.get(0); 

Java 1.4和之前的版本:

 List stringList = new ArrayList(); stringList.add("Hello World"); String hw = (String)stringList.get(0); 

在Java 5中从generics类读取值时,必须强制转换为声明的types参数。 当插入时,编译器将检查您尝试放入的值,如果不是string,则会中止一个错误。

整个过程是为了保持旧的库和新的基因组代码的交互性,而不需要重新编译现有的库。 这是.NET方式的一个主要优势,即generics类和非generics类并行生存,但不能自由交换。

两种方法都有其优点和缺点,但是这正是Java的方式。

回到你原来的问题:在运行时你将无法得到types信息,因为一旦编译器完成了它的工作,它就不存在了。 这在某些方面肯定是有限制的,而且围绕它有一些胡思乱想的方法,通常基于在某处存储类实例,但这不是标准function。

由于types擦除 ,没有办法直接做到这一点。 但是你可以做的是将Class<T>传递给构造函数,并保存在你的类中。 然后你可以根据你允许的三种可能的types来检查它。

但是,如果只有三种可能的types,则可能需要考虑将其重构为一个枚举 。

问题是,大多数通用的东西将在编译过程中消失。

一个常见的解决scheme是在创build对象时保存types。

有关Java的Type Erasure行为的简短介绍,请阅读此页面

如果您知道一些有意义的特定types,则应该使用实现创buildgenericstypes的子类。

所以

 public class Foo<T> public ???? Bar() { //else condition goes here } 

接着

 public class DateFoo extends Foo<Date> public ???? Bar() { //Whatever you would have put in if(T == Date) would go here. } 

generics类的全部要点是你不需要知道正在使用的types….

它看起来像你想要的实际上不是一个通用的类,而是一个接口与许多不同的实现。 但是,如果你说明你的具体实际目标,也许会变得更清楚。

我同意Visage。 generics是用于编译时validation,而不是运行时dynamictypes。 听起来像你所需要的只是工厂模式。 但是如果你的“做这个”不是实例化的,那么一个简单的枚举可能也会起作用。 就像迈克尔说的,如果你有一个更具体的例子,你会得到更好的答案。