上传和下传与类variables有什么区别?

上调和下调相对于类variables有什么区别?

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

如果施法完成,那么我们怎么能把动物的variables称为狗的另一种方法。

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

向上转换为超types,而向下转换则转换为子types。 上传始终是允许的,但向下转换涉及types检查,并可能引发ClassCastException

就你而言,从DogAnimal的演员阵容是一个沉思,因为Dog是一种Animal 。 一般来说,只要两个类之间存在is-a关系,就可以向上转换。

下行会是这样的:

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

基本上你在做的是告诉编译器你知道对象的运行时types是什么。 编译器将允许转换,但仍然会插入运行时的健全性检查,以确保转换有意义。 在这种情况下,投射是可能的,因为在运行时animal实际上是一只Dog即使静态types的animalAnimal

但是,如果你这样做:

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

你会得到一个ClassCastException 。 之所以这样,是因为animal的运行时types是Animal ,所以当你告诉运行时执行转换时,它会发现这个animal并不是一个Dog ,所以抛出一个ClassCastException

要调用超类的方法,你可以做super.method()或者执行super.method()

要调用一个子类的方法,你必须做一个沮丧的事情。 如上所示,通常这样做会导致ClassCastException ; 但是,在执行强制转换之前,可以使用instanceof运算符来检查对象的运行时types,从而可以防止出现ClassCastException s:

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

下铸和上铸如下:
在这里输入图像描述

上传 :自动发生,不需要做任何明确的事情。
向下转换 :在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 

向上转换和向下转换是Java的重要组成部分,它允许我们使用简单的语法来构build复杂的程序,并给予我们很多优点,如多态性或分组不同的对象。 Java允许将子types的对象视为任何超types的对象。 这被称为上传。 上传是自动完成的,而下传必须由程序员手动完成 ,我将尽我所能解释为什么是这样。

向上转换和向下转换不像从一个向另一个转换原语,而且我相信当程序员开始学习转换对象的时候,这会引起很多混乱。

多态性:java中的所有方法默认都是虚拟的。 这意味着任何方法在inheritance时都可以重写,除非该方法被声明为final或static

你可以看下面的例子getType(); 根据对象(狗,宠物,警犬)types工作。

假设你有三只狗

  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"; } } 

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

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

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

打印Normal Dog

  obj2.getType(); 

打印Pet Dog

  obj3.getType(); 

打印Police Dog

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

当你尝试调用secretID(); 方法PoliceDog object这是PoliceDog object但引用到Dog是层次结构中的超类,它抛出错误,因为secretId()没有访问secretId()方法。 为了调用这个方法,你需要手动将 PoliceDog PoliceDog

  ( (PoliceDog)obj3).secretID(); 

打印ID

以类似的方式调用dogName(); 方法在PetDog类中,需要将obj2向下转换为PetDog因为obj2被引用到Dog并且不能访问dogName(); 方法

  ( (PetDog)obj2).dogName(); 

为什么这样,那么上传是自动的,但是下传必须是手动的? 那么,你看,向上投射永远不会失败。 但是,如果你有一群不同的狗,并且想将它们全部PetDog为它们的types,那么有一个机会,就是通过抛出ClassCastException ,这些狗中的一些实际上是不同types的,即PetDogPoliceDog和进程失败。

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

注意:这里通过引用意味着你没有改变你的oject的内存地址,当你downcast它仍然是相同的,你只是把它们分组到特定types在这种情况下Dog

我很早以前就知道这个问题,但对于这个问题的新用户。 请阅读本文,其中包含对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 

为什么会这样,那么上传是自动的,但是下传必须是手动的? 那么,你看,向上投射永远不会失败。 但是,如果你有一群不同的动物,并且想把它们全部下注到一只猫,那么有一个机会,就是这些动物中的一些实际上是狗,并且通过抛出ClassCastExceptionexception而失败。 这是应该引入一个称为“instanceof”的有用特性的地方,它testing某个对象是否是某个Class的实例。

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

欲了解更多信息,请阅读这篇文章

更好地尝试这种方法的上传,很容易理解:

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

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

UPCAST​​ING —> Hidding

向下转换 – >揭示

在这里输入图像描述

输入图像描述他[![在这里输入图片描述 重新] 3 ] 3

父母:车
孩子:菲戈
Car c1 =新的Figo();

=====
向上转型: –
方法:对象c1将引用类的方法(Figo – 方法必须重写),因为类“Figo”是用“new”指定的。
实例variables:对象c1将引用声明类(“Car”)的实例variables。

当声明类是父对象是孩子创build,然后隐式投射发生“上传”。

======
溯造型: –
Figo f1 =(Figo)c1; //
方法:对象f1将引用类方法(figo)作为初始对象c1是用类“Figo”创build的。 但是一旦完成了向下转换,只有类“Figo”中存在的方法也可以通过variablesf1来引用。
实例variables:对象f1不会引用对象c1的声明类的实例variables(c1的声明类是CAR),但是向下转换将引用类Figo的实例variables。

======
使用:当Object是Child类并且声明类是Parent和Child类想要访问它自己的类的Instancevariables而不是父类时,可以使用“Downcasting”来完成。

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

在java中,上传不是必需的,因为它是自动完成的。 它通常被称为隐式投射。 你可以指定它来让别人清楚。

因此,写作

 Animal a = (Animal)d; 

要么

 Animal a = d; 

导致完全相同的点,并在这两种情况下将执行Dogcallme()

因为你定义a动物的对象,所以下转换是必要的。 目前你知道这是一个Dog ,但Java没有保证。 实际上在运行时可能会有所不同,Java会抛出一个ClassCastException ,会发生。 当然,这不是你的例子。 如果你不会施放a Animal ,java甚至不能编译应用程序,因为Animal没有方法callme2()

在你的例子中,你不能从UseAnimlas (因为Dog覆盖它)到达Animalcallme()的代码,除非方法如下:

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

我们可以创build对象向Downcasting。 在这种types也。 :调用基类的方法

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