如何向下转换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
。
你应该只投射到一个对象真正的类,所以如果你有一个扩展Animal
的Dog
你可以把它投射到一个Animal
(因为它是一个)但是你不应该把一个Animal
投射到一只Dog
因为不是所有的Animal
是Dog
的。 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
转换为Bar
或Baz
,尽管类结构似乎意味着你可以。 没有涉及inheritance,因此ClassCastException
。
这里你谈论的是向下转换,所以在这种情况下,总是应该使用超类作为引用,并且应该指向子对象。 这个usd基本上是工厂模式。