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>
是类文件中的简单List
( Object
),就像在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。 听起来像你所需要的只是工厂模式。 但是如果你的“做这个”不是实例化的,那么一个简单的枚举可能也会起作用。 就像迈克尔说的,如果你有一个更具体的例子,你会得到更好的答案。