繁体   English   中英

Java 通用 Class - 确定类型

[英]Java Generic Class - Determine Type

如果我正在创建一个 java class 是通用的,例如:

public class Foo<T>

如何在内部确定 class,“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 等,但我似乎无法弄清它们的正反面。 我觉得我已经很接近了,只需要合并一些电话,但一直没有接电话。

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

我在几个项目中使用了与他在此处解释的内容类似的解决方案,并发现它非常有用。

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 Java generics 相比,它们是通过一种称为“类型擦除”的技术实现的。

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

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

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 中的泛型 class 读取值时,会自动插入对已声明类型参数的必要强制转换。 插入时,编译器将检查您尝试输入的值,如果它不是字符串,则会报错并中止。

整个过程是为了保持旧库和新的通用代码的互操作性,而不需要重新编译现有的库。 与 .NET 方式相比,这是一个主要优势,其中通用类和非通用类并存但不能自由互换。

两种方法各有利弊,但 Java 就是这样。

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

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

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

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

一种常见的解决方案是在创建 Object 期间保存类型。

有关 java 的类型擦除行为的简短介绍,请阅读此页面

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

所以

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.
}

通用 class 的全部要点是您不需要知道正在使用的类型....

看起来您想要的实际上不是通用 class,而是具有许多不同实现的接口。 但如果你陈述你实际的、具体的目标,也许它会变得更清楚。

我同意面貌。 Generics 用于编译时验证,而不是运行时动态类型。 听起来您真正需要的只是工厂模式。 但是,如果您的“执行此操作”不是实例化,那么一个简单的 Enum 可能也能正常工作。 就像 Michael 所说的,如果您有一个更具体的例子,您会得到更好的答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM