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

Dhi*_*kar 124 java casting downcast upcasting class-variables

对于类变量,向上铸造和向下铸造有什么区别?

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

如果完成了施法,那么我们如何使用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();
    }
}
Run Code Online (Sandbox Code Playgroud)

awk*_*ksp 198

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

在你的情况下,从a Dog到a Animal的强制转换是向上的,因为a Dog是a Animal.通常,只要两个类之间存在is-a关系,就可以进行upcast.

向下倾斜会是这样的:

Animal animal = new Dog();
Dog castedDog = (Dog) animal;
Run Code Online (Sandbox Code Playgroud)

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

但是,如果你这样做:

Animal animal = new Animal();
Dog notADog = (Dog) animal;
Run Code Online (Sandbox Code Playgroud)

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

要调用超类的方法,您可以执行super.method()或执行upcast.

要调用子类的方法,您必须进行向下转换.如上所示,您通常会冒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;
}
Run Code Online (Sandbox Code Playgroud)

  • @awksp 这是一个出色而清晰的答案。几乎总结了我需要了解的关于 Casting 的一切。 (2认同)

Pre*_*raj 53

向下和向上铸造如下:
在此输入图像描述

Upcasting:当我们想要将Sub类强制转换为Super类时,我们使用Upcasting(或扩展).它会自动发生,不需要明确地做任何事情.

向下转换:当我们想要将Super类转换为Sub类时,我们使用向下转换(或缩小),而在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
Run Code Online (Sandbox Code Playgroud)


Nag*_*tty 31

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

向上转换和向下转换不像将原语从一个转换为另一个,我相信当程序员开始学习构建对象时,这会引起很多混乱.

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

您可以看到下面的示例如何getType();根据对象(狗,宠物,警犬)类型工作.

假设你有三只狗

  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";
     }
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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();
Run Code Online (Sandbox Code Playgroud)

打印 Normal Dog

  obj2.getType();
Run Code Online (Sandbox Code Playgroud)

打印 Pet Dog

 obj3.getType();
Run Code Online (Sandbox Code Playgroud)

打印 Police Dog

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

当您尝试调用哪个方法但secretID();obj3其中PoliceDog object引用了Dog哪个是层次结构中的超类时,它会抛出错误,因为obj3无法访问secretId()方法.为了调用该方法,您需要手动将obj3向下转换为 PoliceDog

  ( (PoliceDog)obj3).secretID();
Run Code Online (Sandbox Code Playgroud)

打印 ID

以类似的方式调用类中的dogName();方法,PetDog您需要向下转换obj2PetDogobj2被引用,Dog并且无法访问dogName();方法

  ( (PetDog)obj2).dogName();
Run Code Online (Sandbox Code Playgroud)

为什么会这样,这种向上转换是自动的,但是向下转换必须是手动的?嗯,你看,向上转播永远不会失败.但是,如果你有一组不同的狗,并希望他们都垂头丧气到它们的类型,然后有机会的话,其中一些狗实际上是不同类型的,即,PetDog,PoliceDog,和过程失败,抛出ClassCastException.

如果您已将对象引用到超类类型,则需要手动向下转换对象.

注意:这里通过引用意味着当你向下转换它时你没有改变你的对象的内存地址它仍然是相同的你只是在这种情况下将它们分组到特定类型 Dog


Nad*_*hne 12

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

  • 没有必要手动上传,它发生在它自己:

    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
    
    Run Code Online (Sandbox Code Playgroud)

为什么会这样,这种向上转换是自动的,但是向下转换必须是手动的?嗯,你看,向上转播永远不会失败.但是如果你有一组不同的动物并且想要将它们全部转移到一只猫身上,那么就有机会,这些动物中的一些实际上是狗,并且通过抛出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;
    }
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请阅读本文


小智 6

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

/* 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();
    }
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*xis 6

也许这张桌子有帮助.调用callme()Parent或类的方法Child.原则上:

UPCAST​​ING - >隐藏

DOWNCASTING - >揭示

在此输入图像描述

在此输入图像描述

在此输入图像描述


Lem*_*ion 5

1.- 向上倾斜。

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

Animal animalCat = new Cat();
Run Code Online (Sandbox Code Playgroud)

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

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

2.- 垂头丧气。

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

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

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

一些代码的时间:

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

}
Run Code Online (Sandbox Code Playgroud)