例如,我在一个主程序包中超动物类,而在特定的罐子中将“狗”和“猫”子类。所有类都是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);
但是我想念一些东西。
答案 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
。 此操作绝不会转换任何东西。
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实例)。