在java中引用变量downcasting的澄清

时间:2015-01-29 13:11:05

标签: java

以下是示例代码

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();
    }
}

上面的代码汇编得很好但是当我尝试运行它时,我得到了

  

java.lang.ClassCastException

我的假设是它应该打印"通用噪音"因为在运行时它应该调用实际的Animal对象makeNoise()方法而不给出任何异常。

5 个答案:

答案 0 :(得分:4)

您不能将Animal实例强制转换为Dog实例,除非您投射的实例实际上是Dog或{{1}的子类}}

Dog类更抽象是抽象的,因为可以实例化的实际动物应该是特定的动物,例如AnimalDog等。 ..

答案 1 :(得分:3)

如果你有:

Animal animal = new Dog();
Dog dog = (Dog) animal;

没有问题。

您需要了解编译时类型运行时类型之间的区别。在上面的代码片段中,animal的编译时间是Animal,而运行时类型是Dog。这就是 cast Dog没有问题的原因(注意实际的转换是在运行时发生的)。

但是,在您的代码中,animal的运行时类型为Animal(与编译时类型相同)。这意味着animal将指向堆上的对象,该对象支持AnimalmakeNoise())的功能,但不支持Dog的功能这就是ClassCastException发生的原因。

答案 2 :(得分:3)

这里的所有答案在技术上都是正确的。但我想从另一个角度解释这一点。

首先,您定义了一个Animal和一个Dog。到目前为止一切都很好。当您(在DogTest内)创建Animal并将ti转换为Dog时,就会出现此问题。为什么?并非每个Animal都是Dog。我的意思是,Animal可以是BirdCatElephant ......这些Animal不会“吠”。说,您可以将Dog投射为动物,因为所有Dog都是Animal s。

我希望我已经澄清了一下你的想法:)

答案 3 :(得分:0)

它不会打印任何内容,因为您无法使用d.makeNoise()到达该行。当您尝试强制转换为java.lang.ClassCastException某些不是Dog的内容时,会在前一行中抛出Dog

但是,如果没有这一行,您将获得预期的结果:"通用噪音"。

答案 4 :(得分:0)

最好的向下转发我可以通过重写您的代码来解释如下: -

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();
            }
    }

然而,实时这样的需求可以在不使用显式向下转换对象的情况下实现,而不是在Factory Design Pattern的帮助下,我们创建对象而不将创建逻辑暴露给客户端并使用公共接口引用新创建的对象。

可以从here

中提取完整的工厂模式