Java泛型类-确定类型

Java泛型类-确定类型,java,generics,Java,Generics,如果我创建的java类是泛型的,例如: public class Foo<T> 我已经浏览了JavaAPI并使用了反射的东西,instanceof、getClass、class等等,但我似乎无法理解它们的头绪。我觉得我很接近,只需要结合一些电话,但继续短 更具体地说,我试图确定该类是否是用3种可能的类型之一实例化的。因为,无法直接这样做。但是,您可以做的是将类传递到构造函数中,并在类中保留它。然后,您可以对照您允许的三种可能的Class类型进行检查 但是,如果只有三种可能的类型,您

如果我创建的java类是泛型的,例如:

public class Foo<T>
我已经浏览了JavaAPI并使用了反射的东西,instanceof、getClass、class等等,但我似乎无法理解它们的头绪。我觉得我很接近,只需要结合一些电话,但继续短

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

因为,无法直接这样做。但是,您可以做的是将
传递到构造函数中,并在类中保留它。然后,您可以对照您允许的三种可能的
Class
类型进行检查


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

泛型类的全部要点是不需要知道正在使用的类型。

< P>问题是大多数通用的东西在编译过程中会消失。 一种常见的解决方案是在创建对象期间保存类型


要了解java的类型擦除行为的简短介绍,请阅读此

,它看起来实际上不是一个泛型类,而是一个具有许多不同实现的接口。但是,如果你陈述了你的实际的、具体的目标,它可能会变得更清晰。

与.NET不同,Java泛型是通过一种称为“类型擦除”的技术实现的

这意味着编译器在生成类文件时将使用类型信息,但不会将此信息传输到字节码。如果您使用javap或类似工具查看编译后的类,您会发现
列表
是类文件中的一个简单的
列表
(属于
对象
),就像在Java-5之前的代码中一样

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

Java 5:

List<String> stringList = new ArrayList<String>();
stringList.add("Hello World");
String hw = stringList.get(0);
在Java5中从泛型类读取值时,会自动插入对声明的类型参数的必要转换。插入时,编译器将检查您尝试输入的值,如果该值不是字符串,则会以错误终止

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

这两种方法各有优缺点,但在Java中就是这样


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

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

其jist使用以下内容:

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

我同意你的看法。泛型用于编译时验证,而不是运行时动态类型。听起来你需要的只是工厂模式。但是,如果您的“DoThis”不是实例化,那么一个简单的枚举可能也可以工作。就像Michael所说的,如果你有一个更具体的例子,你会得到更好的答案。

如果你知道一些有意义的特定类型,你应该用实现创建泛型类型的子类

所以

公共类Foo
公共????Bar()
{
//否则情况就在这里
}
然后

public class DateFoo extends Foo<Date>

public ???? Bar()
{
    //Whatever you would have put in if(T == Date) would go here.
}
公共类DateFoo扩展了Foo
公共????Bar()
{
//如果(T==Date)在这里,你会输入什么。
}

这样做的愿望几乎肯定是一个糟糕的设计选择。if语句很可能需要了解每个“类型”才能实现,因此您可能应该让所有这些类都属于相同的父类型,“dothis”应该是一个虚拟方法。它可能涉及到包装类,但如果沿着这条路走下去,您的总体设计将得到改进。if语句中的可能性是所有可能调用类型中的边缘情况,这需要完全独立的实现。我同意你在这里所说的,但是具体的应用程序是一个棘手的问题。需要为泛型类型param获取类并不总是一个糟糕的设计决策。一个合法的要求(我的!:)可能是需要类参数的方法调用。对于通用DTO转换器,我也需要这样做。在我看来,这是一个非常合理的问题。尽管如此,如果我设计了一个可以被实例化为任何类型的类,我希望将所有可能类型的特定子集处理为具有特定逻辑的边缘案例。然后创建不同的子类型。或委托给策略(或类似)。这非常有用-我见过涉及这一点的解决方案,可能最终会走这条路。可能意味着你的设计很差。这似乎是最好的解决方案,尽管不如真正的蓝色泛型类漂亮。谢谢你的输入。再次,我敦促你强烈地考虑多态性而不是基于类型的if语句。不幸的是,考虑的项目不以任何方式相关,所以多态解决方案是不实用的。可能属于if语句逻辑的项是所有其他“正常”处理的边缘情况,必须以完全不同的方式进行处理,而不是以任何关系的方式。@dxmio:这些项的关系如下:您正在创建它们的Foo。我并不是说要翻转:您可以创建一个“可食”接口,并让每个接口实现
 public Class returnedClass() {
     ParameterizedType parameterizedType = (ParameterizedType)getClass()
                                                 .getGenericSuperclass();
     return (Class) parameterizedType.getActualTypeArguments()[0];
}
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.
}