简体   繁体   English

在java中引用变量downcasting的澄清

[英]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,例如DogCat等......

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM