上传和下传与类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
。
就你而言,从Dog
到Animal
的演员阵容是一个沉思,因为Dog
是一种Animal
。 一般来说,只要两个类之间存在is-a关系,就可以向上转换。
下行会是这样的:
Animal animal = new Dog(); Dog castedDog = (Dog) animal;
基本上你在做的是告诉编译器你知道对象的运行时types是什么。 编译器将允许转换,但仍然会插入运行时的健全性检查,以确保转换有意义。 在这种情况下,投射是可能的,因为在运行时animal
实际上是一只Dog
即使静态types的animal
是Animal
。
但是,如果你这样做:
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工作。
假设你有三只狗
- 狗 – 这是超级类。
- 宠物狗 – 宠物狗延伸狗。
-
警犬 – 警犬延长宠物狗。
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的,即PetDog
, PoliceDog
和进程失败。
如果您已经将对象引用到超类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()方法。 作为一个原则:
UPCASTING —> 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;
导致完全相同的点,并在这两种情况下将执行Dog
的callme()
。
因为你定义a
动物的对象,所以下转换是必要的。 目前你知道这是一个Dog
,但Java没有保证。 实际上在运行时可能会有所不同,Java会抛出一个ClassCastException
,会发生。 当然,这不是你的例子。 如果你不会施放a
Animal
,java甚至不能编译应用程序,因为Animal
没有方法callme2()
。
在你的例子中,你不能从UseAnimlas
(因为Dog
覆盖它)到达Animal
的callme()
的代码,除非方法如下:
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();