Java 关于类变量的向上转换和向下转换有什么区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23414090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:53:23  来源:igfitidea点击:

What is the difference between up-casting and down-casting with respect to class variable

javacastingclass-variablesdowncastupcasting

提问by Dhivakar

What is the difference between up-casting and down-casting with respect to class variable?

关于类变量,向上转换和向下转换有什么区别?

For example in the following program class Animal contains only one method but Dog class contains two methods, then how we cast the Dog variable to the Animal Variable.

例如在下面的程序中,Animal 类只包含一个方法,而 Dog 类包含两个方法,那么我们如何将 Dog 变量转换为 Animal 变量。

If casting is done then how can we call the Dog's another method with Animal's variable.

如果转换完成,那么我们如何使用 Animal 的变量调用 Dog 的另一个方法。

class Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}


class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class UseAnimlas 
{
    public static void main (String [] args) 
    {
        Dog d = new Dog();      
        Animal a = (Animal)d;
        d.callme();
        a.callme();
        ((Dog) a).callme2();
    }
}

采纳答案by awksp

Upcasting is casting to a supertype, while downcasting is casting to a subtype. Upcasting is always allowed, but downcasting involves a type check and can throw a ClassCastException.

向上转换是转换为超类型,而向下转换是转换为子类型。始终允许向上转换,但向下转换涉及类型检查并且可以抛出ClassCastException.

In your case, a cast from a Dogto an Animalis an upcast, because a Dogis-a Animal. In general, you can upcast whenever there is an is-a relationship between two classes.

在您的情况下,从 aDog到 an 的转换Animal是向上转换,因为 a Dogis-a Animal。一般来说,只要两个类之间存在 is-a 关系,就可以向上转换。

Downcasting would be something like this:

向下转换将是这样的:

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

Basically what you're doing is telling the compiler that you know what the runtime type of the object reallyis. The compiler will allow the conversion, but will still insert a runtime sanity check to make sure that the conversion makes sense. In this case, the cast is possible because at runtime animalis actually a Dogeven though the static type of animalis Animal.

基本上你正在做的是告诉编译器,你知道是什么物体的运行时类型真的是。编译器将允许转换,但仍会插入运行时完整性检查以确保转换有意义。在这种情况下,强制转换是可能的,因为在运行时animal实际上是 aDog即使静态类型animalAnimal

However, if you were to do this:

但是,如果您要这样做:

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

You'd get a ClassCastException. The reason why is because animal's runtime type is Animal, and so when you tell the runtime to perform the cast it sees that animalisn't really a Dogand so throws a ClassCastException.

你会得到一个ClassCastException. 原因是因为它animal的运行时类型是Animal,所以当您告诉运行时执行强制转换时,它会发现这animal不是真正的 a Dog,因此抛出 a ClassCastException

To call a superclass's method you can do super.method()or by performing the upcast.

要调用超类的方法,您可以执行super.method()或执行向上转换。

To call a subclass's method you have to do a downcast. As shown above, you normally risk a ClassCastExceptionby doing this; however, you can use the instanceofoperator to check the runtime type of the object before performing the cast, which allows you to prevent ClassCastExceptions:

要调用子类的方法,您必须进行向下转换。如上所示,您通常会冒险ClassCastException这样做;但是,您可以instanceof在执行强制转换之前使用运算符检查对象的运行时类型,这可以防止ClassCastExceptions:

Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog) {
    // Guaranteed to succeed, barring classloader shenanigans
    Dog castedDog = (Dog) animal;
}

回答by David

upcasting means casting the object to a supertype, while downcasting means casting to a subtype.

向上转换意味着将对象转换为超类型,而向下转换意味着转换为子类型。

In java, upcasting is not necessary as it's done automatically. And it's usually referred as implicit casting. You can specify it to make it clear to others.

在 Java 中,向上转换不是必需的,因为它是自动完成的。它通常被称为隐式转换。您可以指定它以使其他人清楚。

Thus, writing

因此,写

Animal a = (Animal)d;

or

或者

Animal a = d;

leads to exactly the same point and in both cases will be executed the callme()from Dog.

导致完全相同的点,在两种情况下都将执行callme()from Dog

Downcasting is instead necessary because you defined aas object of Animal. Currently you know it's a Dog, but java has no guarantees it's. Actually at runtime it could be different and java will throw a ClassCastException, would that happen. Of course it's not the case of your very sample example. If you wouldn't cast ato Animal, java couldn't even compile the application because Animaldoesn't have method callme2().

相反,向下转换是必要的,因为您定义a为 Animal 的对象。目前你知道它是一个Dog,但 java 不能保证它是。实际上在运行时它可能会有所不同,java 会抛出一个ClassCastException,会发生这种情况。当然,您的示例示例并非如此。如果您不强制转换aAnimal,java 甚至无法编译应用程序,因为Animal没有方法callme2()

In your example you cannot reach the code of callme()of Animalfrom UseAnimlas(because Dogoverwrite it) unless the method would be as follow:

在你的榜样,你无法到达的代码callme()Animal距离UseAnimlas(因为Dog覆盖它),除非该方法是如下:

class Dog extends Animal 
{ 
    public void callme()
    {
        super.callme();
        System.out.println("In callme of Dog");
    }
    ... 
} 

回答by UWAIS

Better try this method for upcasting, it's easy to understand:

最好尝试这种方法进行向上转换,很容易理解:

/* upcasting problem */
class Animal
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}

class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class Useanimlas 
{
    public static void main (String [] args) 
    {
        Animal animal = new Animal ();
        Dog dog = new Dog();
        Animal ref;
        ref = animal;
        ref.callme();
        ref = dog;
        ref.callme();
    }
}

回答by amit shah

Parent: Car
Child: Figo
Car c1 = new Figo();

父:Car
子:Figo
Car c1 = new Figo();

=====
Upcasting:-
Method: Object c1 will refer to Methods of Class (Figo - Method must be overridden) because class "Figo" is specified with "new".
Instance Variable: Object c1 will refer to instance variable of Declaration Class ("Car").

=====
上溯造型: -
方法:景物C1将引用类的方法(菲戈-方法必须被覆盖),因为与“新”的指定类“菲戈”。
实例变量:对象 c1 将引用声明类(“汽车”)的实例变量。

When Declaration class is parent and object is created of child then implicit casting happens which is "Upcasting".

当声明类是父类并且对象是由子对象创建时,就会发生隐式转换,即“向上转换”。

======
Downcasting:-
Figo f1 = (Figo) c1; //
Method: Object f1 will refer to Method of Class (figo) as initial object c1 is created with class "Figo". but once down casting is done, methods which are only present in class "Figo" can also be referred by variable f1.
Instance Variable: Object f1 will not refer to instance variable of Declaration class of object c1 (declaration class for c1 is CAR) but with down casting it will refer to instance variables of class Figo.

======
向下转换:-
Figo f1 = (Figo) c1; //
方法:对象 f1 将引用类的方法(figo),因为初始对象 c1 是用类“Figo”创建的。但是一旦向下转换完成,只存在于“Figo”类中的方法也可以被变量 f1 引用。
实例变量:对象 f1 不会引用对象 c1 的声明类的实例变量(c1 的声明类是 CAR)但向下转换它将引用类 Figo 的实例变量。

======
Use: When Object is of Child Class and declaration class is Parent and Child class wants to access Instance variable of it's own class and not of parent class then it can be done with "Downcasting".

======
使用:当对象是子类并且声明类是父类时,子类想要访问它自己的类而不是父类的实例变量,那么它可以通过“向下转换”来完成。

回答by Nagarjuna Yelisetty

Upcasting and downcasting are important part of Java, which allow us to build complicated programs using simple syntax, and gives us great advantages, like Polymorphism or grouping different objects. Java permits an object of a subclass type to be treated as an object of any superclass type. This is called upcasting. Upcasting is done automatically, while downcasting must be manually done by the programmer, and i'm going to give my best to explain why is that so.

Upcasting 和 downcasting 是 Java 的重要组成部分,它允许我们使用简单的语法构建复杂的程序,并为我们提供了很大的优势,比如多态性或对不同对象进行分组。Java 允许将子类类型的对象视为任何超类类型的对象。这称为向上转换。Upcasting 是自动完成的,而 downcasting 必须由程序员手动完成,我将尽力解释为什么会这样。

Upcasting and downcasting are NOT like casting primitives from one to other, and i believe that's what causes a lot of confusion, when programmer starts to learn casting objects.

Upcasting 和 downcasting 不像将原语从一个转换到另一个,我相信这是导致很多混乱的原因,当程序员开始学习转换对象时。

Polymorphism: All methods in java are virtual by default. That means that any method can be overridden when used in inheritance, unless that method is declared as final or static.

多态性:java中的所有方法默认都是虚拟的。这意味着在继承中使用任何方法都可以被覆盖,除非该方法被声明为 final 或 static

You can see the example below how getType();works according to the object(Dog,Pet,Police Dog) type.

您可以在下面的示例中看到getType();根据对象(狗、宠物、警犬)类型的工作方式。

Assume you have three dogs

假设你有三只狗

  1. Dog - This is the super Class.
  2. Pet Dog - Pet Dog extends Dog.
  3. Police Dog - Police Dog extends Pet Dog.

    public class Dog{ 
       public String getType () {
          System.out.println("NormalDog");
          return "NormalDog";
       }
     }
    
    /**
     * Pet Dog has an extra method dogName()
     */   
    public class PetDog extends Dog{ 
       public String getType () {
          System.out.println("PetDog");
          return "PetDog";
       }
       public String dogName () {
          System.out.println("I don't have Name !!");
          return "NO Name";
       }
     }
    
    /**
     * Police Dog has an extra method secretId()
     */
    public class PoliceDog extends PetDog{
    
     public String secretId() {
        System.out.println("ID");
        return "ID";
     }
    
     public String getType () {
         System.out.println("I am a Police Dog");
         return "Police Dog";
     }
    }
    
  1. 狗 - 这是超级班。
  2. 宠物狗 - 宠物狗扩展了狗。
  3. 警犬 - 警犬延伸宠物狗。

    public class Dog{ 
       public String getType () {
          System.out.println("NormalDog");
          return "NormalDog";
       }
     }
    
    /**
     * Pet Dog has an extra method dogName()
     */   
    public class PetDog extends Dog{ 
       public String getType () {
          System.out.println("PetDog");
          return "PetDog";
       }
       public String dogName () {
          System.out.println("I don't have Name !!");
          return "NO Name";
       }
     }
    
    /**
     * Police Dog has an extra method secretId()
     */
    public class PoliceDog extends PetDog{
    
     public String secretId() {
        System.out.println("ID");
        return "ID";
     }
    
     public String getType () {
         System.out.println("I am a Police Dog");
         return "Police Dog";
     }
    }
    

Polymorphism : All methods in java are virtual by default. That means that any method can be overridden when used in inheritance, unless that method is declared as final or static.(Explanation Belongs to Virtual Tables Concept)

多态性:默认情况下,java 中的所有方法都是虚拟的。这意味着在继承中使用时任何方法都可以被覆盖,除非该方法被声明为 final 或 static。(解释属于虚拟表概念)

Virtual Table / Dispatch Table : An object's dispatch table will contain the addresses of the object's dynamically bound methods. Method calls are performed by fetching the method's address from the object's dispatch table. The dispatch table is the same for all objects belonging to the same class, and is therefore typically shared between them.

虚拟表/调度表:对象的调度表将包含对象的动态绑定方法的地址。方法调用是通过从对象的调度表中获取方法的地址来执行的。分派表对于属于同一类的所有对象都是相同的,因此通常在它们之间共享。

public static void main (String[] args) {
      /**
       * Creating the different objects with super class Reference
       */
     Dog obj1 = new Dog();
`         /**
           *  Object of Pet Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry about it 
           *  
           */
     Dog obj2 = new PetDog();
`         /**
           *  Object of Police Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry       
           *  about it here even though we are extending PoliceDog with PetDog 
           *  since PetDog is extending Dog Java automatically upcast for us 
           */
      Dog obj3 = new PoliceDog();
}



 obj1.getType();

Prints Normal Dog

印刷 Normal Dog

  obj2.getType();

Prints Pet Dog

印刷 Pet Dog

 obj3.getType();

Prints Police Dog

印刷 Police Dog

Downcasting need to be done by the programmer manually

向下转换需要由程序员手动完成

When you try to invoke the secretID();method on obj3which is PoliceDog objectbut referenced to Dogwhich is a super class in the hierarchy it throws error since obj3don't have access to secretId()method.In order to invoke that method you need to Downcast that obj3 manually toPoliceDog

当您尝试调用secretID();的方法,obj3这是PoliceDog object但参考Dog这是因为它抛出错误的层次结构中的超类obj3没有访问secretId()方法。为了调用该方法,您需要手动将该 obj3 向下转换为PoliceDog

  ( (PoliceDog)obj3).secretID();

which prints ID

哪个打印 ID

In the similar way to invoke the dogName();method in PetDogclass you need to downcast obj2to PetDogsince obj2 is referenced to Dogand don't have access to dogName();method

在类似的方式来调用的dogName();方法PetDog类,你需要向下转换obj2PetDog自OBJ2为参考Dog,并没有获得dogName();方法

  ( (PetDog)obj2).dogName();

Why is that so, that upcasting is automatical, but downcasting must be manual? Well, you see, upcasting can never fail. But if you have a group of different Dogs and want to downcast them all to a to their types, then there's a chance, that some of these Dogs are actually of different types i.e., PetDog, PoliceDog, and process fails, by throwing ClassCastException.

为什么会这样,向上转换是自动的,而向下转换必须是手动的?好吧,你看,向上转型永远不会失败。但是,如果您有一组不同的 Dog 并且想要将它们全部降级为 a 到它们的类型,那么有可能这些 Dog 中的一些实际上属于不同类型,即PetDog, PoliceDog,并且过程失败,通过抛出ClassCastException

This is the reason you need to downcast your objects manuallyif you have referenced your objects to the super class type.

如果您已将对象引用到超类类型,这就是您需要手动向下转换对象的原因。

Note: Here by referencing means you are not changing the memory address of your ojects when you downcast it it still remains same you are just grouping them to particular type in this case Dog

注意:这里通过引用意味着您在向下转换时不会更改对象的内存地址它仍然保持不变在这种情况下您只是将它们分组为特定类型 Dog

回答by Nadeesha Thilakarathne

I know this question asked quite long time ago but for the new users of this question. Please read this article where contains complete description on upcasting, downcasting and use of instanceofoperator

我知道这个问题很久以前就问过了,但是对于这个问题的新用户。请阅读这篇文章,其中包含有关instanceof运算符的向上转换、向下转换和使用的完整说明

  • There's no need to upcast manually, it happens on its own:

    Mammal m = (Mammal)new Cat();equals to Mammal m = new Cat();

  • But downcasting must always be done manually:

    Cat c1 = new Cat();      
    Animal a = c1;      //automatic upcasting to Animal
    Cat c2 = (Cat) a;    //manual downcasting back to a Cat
    
  • 无需手动向上转换,它会自行发生:

    Mammal m = (Mammal)new Cat();等于 Mammal m = new Cat();

  • 但是向下转换必须始终手动完成:

    Cat c1 = new Cat();      
    Animal a = c1;      //automatic upcasting to Animal
    Cat c2 = (Cat) a;    //manual downcasting back to a Cat
    

Why is that so, that upcasting is automatical, but downcasting must be manual? Well, you see, upcasting can never fail. But if you have a group of different Animals and want to downcast them all to a Cat, then there's a chance, that some of these Animals are actually Dogs, and process fails, by throwing ClassCastException. This is where is should introduce an useful feature called "instanceof", which tests if an object is instance of some Class.

为什么会这样,向上转换是自动的,而向下转换必须是手动的?好吧,你看,向上转型永远不会失败。但是,如果您有一组不同的 Animal 并且想要将它们全部降级为 Cat,那么有可能这些 Animal 中的一些实际上是 Dog,并且过程会通过抛出 ClassCastException 失败。这是应该引入一个名为“instanceof”的有用特性的地方,它测试一个对象是否是某个类的实例。

 Cat c1 = new Cat();         
    Animal a = c1;       //upcasting to Animal
    if(a instanceof Cat){ // testing if the Animal is a Cat
        System.out.println("It's a Cat! Now i can safely downcast it to a Cat, without a fear of failure.");        
        Cat c2 = (Cat)a;
    }

For more information please read this article

有关更多信息,请阅读这篇文章

回答by Premraj

Down-casting and up-casting was as follows:
enter image description here

向下铸造和向上铸造如下:
在此处输入图片说明

Upcasting: When we want to cast a Sub class to Super class, we use Upcasting(or widening). It happens automatically, no need to do anything explicitly.

Upcasting:当我们想将一个子类转换为超类时,我们使用 Upcasting(或加宽)。它会自动发生,无需显式执行任何操作。

Downcasting: When we want to cast a Super class to Sub class, we use Downcasting(or narrowing), and Downcasting is not directly possible in Java, explicitly we have to do.

Downcasting:当我们想将 Super 类转换为 Sub 类时,我们使用 Downcasting(或缩小),而 Downcasting 在 Java 中不能直接进行,我们必须明确地这样做。

Dog d = new Dog();
Animal a = (Animal) d; //Explicitly you have done upcasting. Actually no need, we can directly type cast like Animal a = d; compiler now treat Dog as Animal but still it is Dog even after upcasting
d.callme();
a.callme(); // It calls Dog's method even though we use Animal reference.
((Dog) a).callme2(); // Downcasting: Compiler does know Animal it is, In order to use Dog methods, we have to do typecast explicitly.
// Internally if it is not a Dog object it throws ClassCastException

回答by Rakesh

We can create object to Downcasting. In this type also. : calling the base class methods

我们可以创建向下转换的对象。在这种类型也。: 调用基类方法

Animal a=new Dog();
a.callme();
((Dog)a).callme2();

回答by Alexis

Maybe this table helps. Calling the callme()method of class Parentor class Child. As a principle:

也许这张桌子有帮助。调用callme()classParent或 class的方法Child。作为一个原则:

UPCASTING --> Hiding

DOWNCASTING --> Revealing

向上播放 --> 隐藏

贬低 --> 揭示

enter image description here

在此处输入图片说明

enter image description here

在此处输入图片说明

enter image description here

在此处输入图片说明

回答by Lemmy_Caution

1.- Upcasting.

1.- 向上倾斜。

Doing an upcasting, you define a tag of some type, that points to an object of a subtype(Type and subtype may be called class and subclass, if you feel more comfortable...).

进行向上转换,您定义某种类型的标记,该标记指向子类型的对象(如果您觉得更舒服,类型和子类型可以称为类和子类……)。

Animal animalCat = new Cat();

What means that such tag, animalCat, will have the functionality (the methods) of type Animal only, because we've declared it as type Animal, not as type Cat.

这意味着,animalCat 这样的标记将仅具有 Animal 类型的功能(方法),因为我们已将其声明为 Animal 类型,而不是 Cat 类型。

We are allowed to do that in a "natural/implicit/automatic" way, at compile-time or at a run-time, mainly because Cat inherits some of its functionality from Animal; for example, move(). (At least, cat is an animal, isn't it?)

我们可以在编译时或运行时以“自然/隐式/自动”的方式这样做,主要是因为 Cat 继承了 Animal 的一些功能;例如,移动()。(至少,猫是一种动物,不是吗?)

2.- Downcasting.

2.- 垂头丧气。

But, what would happen if we need to get the functionality of Cat, from our type Animal tag?.

但是,如果我们需要从我们的类型 Animal 标签中获取 Cat 的功能会发生什么?

As we have created the animalCat tag pointing to a Cat object, we need a way to call the Cat object methods, from our animalCat tag in a some smart pretty way.

由于我们已经创建了指向 Cat 对象的animalCat 标记,因此我们需要一种方法来调用 Cat 对象的方法,从我们的animalCat 标记以某种巧妙的方式调用。

Such procedure is what we call Downcasting, and we can do it only at the run-time.

这样的过程就是我们所说的Downcasting,我们只能在运行时进行。

Time for some code:

一些代码的时间:

public class Animal {
    public String move() {
        return "Going to somewhere";
    }
}

public class Cat extends Animal{
    public String makeNoise() {
        return "Meow!";
    }   
}

public class Test {

    public static void main(String[] args) {

    //1.- Upcasting 
    //  __Type_____tag________object
        Animal animalCat = new Cat();
    //Some animal movement
        System.out.println(animalCat.move());
        //prints "Going to somewhere"

    //2.- Downcasting   
    //Now you wanna make some Animal noise.
        //First of all: type Animal hasn't any makeNoise() functionality.
        //But Cat can do it!. I wanna be an Animal Cat now!!

        //___________________Downcast__tag_____ Cat's method
        String animalNoise = ( (Cat) animalCat ).makeNoise();

        System.out.println(animalNoise);
        //Prints "Meow!", as cats usually done.

    //3.- An Animal may be a Cat, but a Dog or a Rhinoceros too.
        //All of them have their own noises and own functionalities.
        //Uncomment below and read the error in the console:

    //  __Type_____tag________object
        //Cat catAnimal = new Animal();

    }

}