如何向下转换Java对象?

我试图理解Java的多态性,我有一个关于向下转换对象的问题。 让我们说这个例子我有两个inheritance自超类Animal的子类Dog和Cat

根据我的理解,向下转换对象的唯一方法是,如果此Object已经是好的类型,如下所示:

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

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

最简单的forms:

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

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

你应该只投射到一个对象真正的类,所以如果你有一个扩展AnimalDog你可以把它投射到一个Animal (因为它是一个)但是你不应该把一个Animal投射到一只Dog因为不是所有的AnimalDog的。 Dog类可能有一些额外的字段,这些字段不是由Animal类实现的,因此转换没有意义(你将这些值初始化为什么?)。

Java是一种强类型语言,这意味着您只能将对象转换为它所扩展的类型(超类或接口)。

即使你“假装”,例如复制所有类方法和字段,你也无法将对象强制转换为它不扩展的类型。

 public class Foo{ public String phleem; public void bar(){ } } public class Bar{ public String phleem; } public interface Baz{ public void bar(); } 

鉴于上面的代码,你不能将Foo对象Foo转换为BarBaz ,尽管类结构似乎意味着你可以。 没有涉及inheritance,因此ClassCastException

这里你谈论的是向下转换,所以在这种情况下,总是应该使用超类作为引用,并且应该指向子对象。 这个usd基本上是工厂模式。

Interesting Posts