[英]Clarification in reference variable downcasting in java
Below is the sample code 下面是示例代码
class Animal {
void makeNoise() {System.out.println("generic noise"); }
}
class Dog extends Animal {
void makeNoise() {System.out.println("bark"); }
void playDead() { System.out.println("roll over"); }
}
class DogTest {
public static void main(String [] args) {
Animal animal = new Animal();
Dog d = (Dog) animal;
d.makeNoise();
}
}
Above code compiles well but when i try to run it, i get 上面的代码汇编得很好但是当我尝试运行它时,我得到了
java.lang.ClassCastException java.lang.ClassCastException
My assumption is it should print "generic noise" because at run time it should invoke actual Animal object makeNoise() method without giving any exception. 我的假设是它应该打印“泛型噪声”,因为在运行时它应该调用实际的Animal对象makeNoise()方法而不给出任何异常。
You can't cast an arbitrary Animal
instance to a Dog
instance, unless the instance you are casting is actually a Dog
or a sub-class of Dog
. 你不能任意投Animal
例如为Dog
的实例,除非你是铸造实例实际上是Dog
或子类Dog
。
It would make more sense for the Animal
class to be abstract, since an actual Animal that can be instantiated should be a specific Animal, such as Dog
, Cat
, etc... 对于Animal
类来说,抽象是更有意义的,因为可以实例化的实际Animal应该是特定的Animal,例如Dog
, Cat
等......
If you had: 如果你有:
Animal animal = new Dog();
Dog dog = (Dog) animal;
there would be no problem. 没有问题。
You need to understand the difference between compile-time type and runtime type . 您需要了解编译时类型和运行时类型之间的区别。 In the code snippet above, the compile-time time of animal
is Animal
, while the runtime type is Dog
. 在上面的代码片段中, animal
的编译时间是Animal
,而运行时类型是Dog
。 This is why there's no problem casting to Dog
(note that the actual casting happens at runtime). 这就是为什么没有问题转换为Dog
(注意实际的转换发生在运行时)。
In your code, however, the runtime type of animal
is Animal
(same as the compile-time type). 但是,在您的代码中, animal
的运行时类型是Animal
(与编译时类型相同)。 This means that the animal
will point to an object on the heap, that supports the features of an Animal
(which is makeNoise()
), but not the features of a Dog
and that's why the ClassCastException
happens. 这意味着animal
将指向堆上的对象,它支持Animal
的功能(即makeNoise()
),但不支持Dog
的功能,这就是ClassCastException
发生的原因。
All answers here are technically correct. 这里的所有答案都是技术上正确的。 But I want to explain this from an other point of view. 但我想从另一个角度来解释这一点。
First off, you have defined one Animal
and one Dog
. 首先,你定义了一只Animal
和一只Dog
。 So far everything is fine. 到目前为止一切都很好。 The problem comes when you (within DogTest
) create an Animal
and cast ti as Dog
. 当你(在DogTest
内)创建一个Animal
并将其作为Dog
施放时,问题就来了。 Why? 为什么? Not every Animal
is a Dog
. 不是每个Animal
都是Dog
。 I mean, an Animal
can be a Bird
, a Cat
, an Elephant
... These Animal
s do not "bark". 我的意思是, Animal
可以是一只Bird
,一只Cat
,一只Elephant
......这些Animal
不会“吠叫”。 Said that, you do can cast a Dog
as an Animal because all Dog
s are Animal
s. 说,你可以把Dog
当作动物,因为所有的Dog
都是Animal
的。
I hope I have clarified a bit your mind :) 我希望我已经澄清了一下你的想法:)
It won't print anything, because you won't reach the line with d.makeNoise()
. 它不会打印任何内容,因为您无法使用d.makeNoise()
到达该行。 The java.lang.ClassCastException
is thrown in the earlier line, when you try to cast to Dog
something, which is not Dog
. java.lang.ClassCastException
在前面的行中抛出,当你尝试强制转换为Dog
,而不是Dog
。
Still, without this line, you'll get the expected result: "generic noise". 但是,如果没有这一行,你将获得预期的结果:“通用噪音”。
Best possible downcasting i can explain by re-writing your code as follows :- 最好的向下转发我可以通过重写您的代码来解释如下: -
public interface Animal {
public void show();
}
public abstract class Dog implements Animal {
public void display(){
System.out.println("Dog Called");
}
}
public class Impl extends Dog{
@Override
public void show() {
System.out.println("Impl Called");
}
}
class DogTest {
public static void main(String [] args) {
Animal a = new Impl();
/**
* child class's method tried to be accessed with the help of
* parent class's object using downcasting of object
* */
((Dog)a).display();
}
}
However real time such requirements can fulfilled without using explicit downcasting of objects instead with the help of Factory Design Pattern in which we create object without exposing the creation logic to the client and refer to newly created object using a common interface. 然而,实时这样的需求可以在不使用显式向下转换对象的情况下实现,而不是在Factory Design Pattern的帮助下,我们在其中创建对象而不将创建逻辑暴露给客户端并使用公共接口引用新创建的对象。
Complete factory pattern can be pulled from here 完整的工厂模式可以从这里拉出来
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.