Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-使用超类对象数组避免强制转换_Java_Arrays_Casting_Clone_Subclass - Fatal编程技术网

Java-使用超类对象数组避免强制转换

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的子类(Dog、Cat、Mouse等)

因此,我:

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:一个接口可以扩展另一个接口:
公共接口动物扩展可克隆性
。没问题。不知道为什么不工作:(顺便说一句,我用抽象的方法解决了,你是上帝,谢谢!