JAVA反射将对象转换为由特定超类型名称给定的类

时间:2019-01-24 18:19:08

标签: java generics reflection

例如,我在一个主程序包中超动物类,而在特定的罐子中将“狗”和“猫”子类。所有类都是JPA实体。

public class Animal {
}

public class Dog extends Animal{
}

public class Cat extends Animal{
}

我有一种将Animal作为参数的方法。

public createAnimal(Animal a){
   this.em.persist(a);
}

现在我想将Dog或Cat类型的对象传递给该方法

Animal a = ... //read from somewhere...
String myClass = "my.package.Dog";// at runtime
Class specific = Class.forName(myClass);
createAnimal(specific.cast(a));

我不能在我的主软件包中导入Dog and Cat,因为它必须是通用的(我在其他EAR中使用了它)。

那么,如何转换为按名称定义的特定类,并让系统知道那是Animal的子类型?

我需要这样的东西:

Class<Animal> specific = Class.forName(myClass);

但是我想念一些东西。

1 个答案:

答案 0 :(得分:0)

您似乎对转换功能感到困惑。强制转换语法如下:(Dog) someAnimal;完成3个完全不相关的事情。

1)它首先要做的是强制类型,它实际上将值从一种转换为另一种。仅当parens中的内容是原始的时,您才能获得此信息。示例:int x = (int) 5.5;将“强制” 5.5(这是一个双精度)转换为5(一个int)。

2)第二件事是类型检查。这是在paren中的事物是非原始类型,而不是没有特定于表达式的类型的情况下发生的情况。因此,例如:Animal a = someAnimal(); Dog d = (Dog) a;。您似乎认为此操作将动物转化为狗。它不是。这一切都是类型检查:a是类型Animal的变量,这意味着它要么指向null,要么指向某个对象,该对象要么是Animal的实例(该类本身或其任何子类型。完全可以使“ a”为Animal类型并指向Cat类型的对象(这是Animal的子类型)。编写(Dog) a会进行类型检查:如果a当前指向类Dog的某个实例或为null,则此操作完全不执行任何操作。如果当前未指向狗(例如,它指向猫),则该表达式将引发ClassCastException此操作绝不会转换任何东西

  1. 最后一种最深奥的用法是在其中执行类似以下操作:Dog d = someDog(); Animal a = (Animal) d;。在大多数情况下,这是完全禁止操作的操作,您的IDE会警告您,这样做完全没有意义。 Animal a = d;合法。但是,类型仍然会更改,这可能会影响您正在调用的方法以及将要键入的lambda。如果这对您来说是愚蠢的,请不要担心。这基本上不会出现。

您似乎还会感到困惑:

对变量Class<Animal>的唯一有效分配是Animal.class(并且为null)。 Dog.class不允许在那里。如果这是您的意图,则正确的类型为Class<? extends Animal>

您可以使用任何类的cast方法来反射地投射 INSTANCES 。例如:

Dog dog = Dog.class.cast(someAnimal());
Dog dog = (Dog) someAnimal();

完全等效:什么都不做,除非someAnimal()返回一个非dog,在这种情况下,它将导致ClassCastException抛出。

如果要检查某些类实例是否与动物兼容,可以执行以下操作:

Class<?> dogClass = Dog.class;
if (!Animal.class.isAssignableFrom(dogClass)) { /* error here */ }

或者有asSubclass:

Class<? extends Animal> animalClass = Dog.class;
Class<? extends Dog> dogClass = animalClass.asSubclass(Dog.class);
assert dogClass == animalClass;

请注意,asSubclass方法又不会执行任何操作,只会使javac停止抱怨。在运行时,消除了泛型;全部都是Class<>中的位就消失了。因此,dogClass和animalClass是两个变量,都指向完全相同的对象(即,代表Dog类的j.l.Class实例)。