Java通用类 - 确定类型

Ben*_*key 49 java generics

如果我创建一个通用的java类,例如:

public class Foo<T>
Run Code Online (Sandbox Code Playgroud)

如何确定那个类的内部,'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
}
Run Code Online (Sandbox Code Playgroud)

我已经开始使用Java API并使用Reflection的东西,instanceof,getClass,.class等,但我似乎无法对它们做出正面或反面.我觉得我很接近,只需要结合一些电话,但不断提出来.

更具体地说,我试图确定该类是否使用3种可能类型之一进行实例化.

jnt*_*t30 58

我已经使用了类似的解决方案来解释他在这里解释的一些项目,并发现它非常有用.

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];
}
Run Code Online (Sandbox Code Playgroud)

  • 给我`线程中的异常"main"java.lang.ClassCastException:java.lang.Class无法强制转换为java.lang.reflect.ParameterizedType`您确定这有效吗? (13认同)
  • 以下是Android中发生的情况:getClass().getGenericSuperclass()返回一个表示java.lang.Object的Class对象,该对象不会强制转换为ParameterizedType.如果您的类继承了伪Base <T>,则返回值表示"Base <T>",而getActualTypeArguments()[0]返回的是名为"T"的Type,它甚至不会转换为Class.不行. (11认同)
  • 值得注意的是,这仅适用于在java代码中显式声明类型参数的类.这种类型的逻辑不适用于通过动态代理实现的模拟. (3认同)

Dan*_*ler 44

与.NET相比,Java泛型是通过一种称为"类型擦除"的技术实现的.

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

访问通用List的代码将被编译器"重写",以包含您必须在早期版本中自己编写的强制转换.实际上,一旦编译器使用它们,从字节代码的角度看,以下两个代码片段是相同的:

Java 5:

List<String> stringList = new ArrayList<String>();
stringList.add("Hello World");
String hw = stringList.get(0);
Run Code Online (Sandbox Code Playgroud)

Java 1.4及之前版本:

List stringList = new ArrayList();
stringList.add("Hello World");
String hw = (String)stringList.get(0);
Run Code Online (Sandbox Code Playgroud)

在Java 5中从泛型类中读取值时,将自动插入对声明的类型参数的必要强制转换.插入时,编译器将检查您尝试放入的值,如果它不是String,则中止错误.

整个过程是为了保持旧库和新的通用代码可以互操作,而无需重新编译现有的库.这是.NET方法的一个主要优点,其中泛型类和非泛型类并存,但不能自由互换.

这两种方法各有利弊,但这就是Java的方式.

回到原来的问题:你将无法在运行时获取类型信息,因为一旦编译器完成其工作,它就不再存在了.这肯定会在某些方面受到限制,并且它周围有一些胡思乱想的方法,通常基于在某处存储类实例,但这不是标准功能.


Mic*_*ers 12

由于类型擦除,无法直接执行此操作.但是,你可以做的是传递给Class<T>构造函数并在你的类中保留它.然后,您可以根据Class您允许的三种可能类型进行检查.

但是,如果只有三种可能的类型,您可能需要考虑重构为枚举.