如何向下转换 Java 对象?

2022-09-02 01:54:14

我试图理解Java的多态性,我有一个关于向下转换对象的问题。假设在这个例子中,我有两个子类Dog和Cat,它们继承自超类动物

根据我的理解,向下转换对象的唯一方法是如果这个对象已经是好的类型,就像这样:

Animal a = new Dog();
Dog d = (Dog) a;

这有效吗?

但是,如果我想在不知道它是什么的情况下创造一个普通的动物,然后在我知道的时候把它扔掉,我该怎么做呢?

Animal a = new Animal();
Dog d = (Dog) a;

这将在运行时抛出一个ClassCastException,对吗?

我发现这样做的唯一方法是创建一个新的Dog构造函数,从常规动物创建狗:

Animal a = new Animal();
Dog d = new Dog(a);

public Class Dog extends Animal{
   public Dog(Animal a){
      super(a);
   }
}

所以我的问题是,我应该如何做到这一点?

  • 我这样做是最好的方法吗?
  • 难道我根本不应该这样做,如果我必须这样做,这意味着我的程序构思得不好吗?
  • 有没有更好的方法我错过了?

多谢!nbarraille


答案 1

如果要创建可能因非局部条件而异的类型实例,请使用抽象工厂(如《设计模式》一书中所述)。

在最简单的形式中:

interface AnimalFactory {
    Animal createAnimal();
}

class DogFactory implements AnimalFactory {
    public Dog createAnimal() {
        return new Dog();
    }
}

另请注意,引用的静态类型与对象的动态类型之间存在差异。即使您有引用,如果原始对象是 ,它仍然表现得像 .AnimalDogDog


答案 2

你应该只强制转换为对象真正存在的类,因此,如果你有一个扩展,你可以将其强制转换为一个(因为它是一个),但你不应该将一个强制转换为a,因为并非所有的s都是s。该类很可能具有未由类实现的额外字段,因此强制转换没有意义(您将这些值初始化为什么?)。DogAnimalAnimalAnimalDogAnimalDogDogAnimal