Java-使用超类对象数组避免强制转换
我有许多实现超类Animal的子类(Dog、Cat、Mouse等) 因此,我:Java-使用超类对象数组避免强制转换,java,arrays,casting,clone,subclass,Java,Arrays,Casting,Clone,Subclass,我有许多实现超类Animal的子类(Dog、Cat、Mouse等) 因此,我: Animal[] arrayOfAnimals = new Animal[100]; 我把狗、猫等东西放进去 当我从中得到一些东西时,我就做了 If(arrayOfAnimals[1] instanceof Dog) { ((Dog)(arrayOfAnimals[1])).speak(); } else if(arrayOfAnimals[1] instanceof Cat) { ((Cat)(
Animal[] arrayOfAnimals = new Animal[100];
我把狗、猫等东西放进去
当我从中得到一些东西时,我就做了
If(arrayOfAnimals[1] instanceof Dog) {
((Dog)(arrayOfAnimals[1])).speak();
}
else if(arrayOfAnimals[1] instanceof Cat) {
((Cat)(arrayOfAnimals[1])).speak();
}
因为我需要知道那只动物是猫还是狗,因为,例如,每只动物说话的方式都不同
现在假设我有很多动物的子类,我会连续地得到很多“else if…”
我的问题是:有没有办法避免这种情况?我已经尝试过使用接口(Animal->interface,Dog,Cat等实现Animal),但在我的项目中,数组必须是可克隆的,如果Animal是接口,则不能克隆数组“Animal[]arrayOfAnimals”(该数组中的对象不会被克隆)
因为我需要知道那只动物是猫还是狗,因为,例如,每只动物说话的方式都不同
这听起来像是一个实现细节——如果每个动物都能以某种形式说话,那么应该将speak()
方法作为抽象方法放入animal
。然后,每个子类将覆盖它以提供实现。那你就可以用
arrayOfAnimals[1].speak();
。。。多态性将负责使用正确的实现
您可以克隆接口类型的数组,顺便说一句:
interface Foo {
}
class FooImpl implements Foo {
}
public class Test {
public static void main(String[] args) {
Foo[] foos = { new FooImpl() };
Foo[] clone = (Foo[]) foos.clone();
System.out.println(foos[0] == clone[0]); // true
}
}
请注意,无论涉及何种类型,对数组调用
clone()
都不会克隆每个元素-新数组将包含与旧数组相同的引用。这是一个肤浅的副本。如果你想这样做,你必须自己编写代码(或者找第三方库)。为什么不将speak()移动到超类,让子类覆盖它?因为当你使用arrayOfAnimals[1]。speak()时,他将使用超类动物的方法。现在我将尝试将其定义为抽象,就像Jon Skeet Saidumm,不,它不会。JVM使用虚拟方法调用动态选择将运行的方法的实际版本。因此,您不能调用任何未在Animal中声明的方法,但您调用的任何方法都将在实际引用的实例类型上调用。如果你像约翰·斯基特所说的那样把它抽象化——顺便说一句,这并没有错——你只是在强迫它被覆盖。最终的结果是相同的,相同的原则。另一方面,您可以通过为其提供实现来指定默认实现。将克隆阵列,但不会克隆其中的对象。尝试使用System.out.println(arrayOfAnimals[1]);和System.out.println(arracycloned[1]);:他们吃的是同样的杂烩id@FrancescoTronca:是的,我在最后一段是这么说的。无论数组类型是否为接口,都会发生这种情况。我尝试过,这就是为什么你不能克隆接口数组(假设你也想克隆其中的对象):如果动物是接口,你不能克隆动物对象,因为动物不能实现可克隆(一个接口不能实现另一个=P)@FrancescoTronca:一个接口可以扩展另一个接口:公共接口动物扩展可克隆性
。没问题。不知道为什么不工作:(顺便说一句,我用抽象的方法解决了,你是上帝,谢谢!