对于类变量,向上铸造和向下铸造有什么区别?
例如,在下面的程序类中,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(); } }
awksp.. 198
向上转换为超类型,而向下转换则转换为子类型.始终允许向上转换,但是向下转换涉及类型检查并且可以抛出ClassCastException
.
在你的情况下,从a Dog
到a Animal
的强制转换是向上的,因为a Dog
是a Animal
.通常,只要两个类之间存在is-a关系,就可以进行upcast.
向下倾斜会是这样的:
Animal animal = new Dog(); Dog castedDog = (Dog) animal;
基本上你正在做的是告诉你知道什么该对象的运行时类型的编译器真的是.编译器将允许转换,但仍将插入运行时完整性检查以确保转换有意义.在这种情况下,中投可能是因为在运行时animal
实际上是Dog
即使静态类型的animal
是Animal
.
但是,如果你这样做:
Animal animal = new Animal(); Dog notADog = (Dog) animal;
你会得到一个ClassCastException
.原因是因为animal
运行时类型是Animal
,所以当你告诉运行时执行强制转换时,它会发现它animal
不是真的Dog
,所以抛出一个ClassCastException
.
要调用超类的方法,您可以执行super.method()
或执行upcast.
要调用子类的方法,您必须进行向下转换.如上所示,您通常会冒ClassCastException
这样做的风险; 但是,您可以instanceof
在执行强制转换之前使用运算符检查对象的运行时类型,这样可以防止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; }
Premraj.. 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
Nagarjuna Ye.. 31
向上转换和向下转换是Java的重要组成部分,它允许我们使用简单的语法构建复杂的程序,并为我们提供了很多优势,例如多态或分组不同的对象.Java允许将子类类型的对象视为任何超类类型的对象.这称为向上转播.向上转换是自动进行的,而向下转换必须由程序员手动完成,我将尽力解释为什么会如此.
向上转换和向下转换不像将原语从一个转换为另一个,我相信当程序员开始学习构建对象时,这会引起很多混乱.
多态性:默认情况下,java中的所有方法都是虚拟的.这意味着在继承中使用任何方法都可以被覆盖,除非该方法被声明为final或static.
您可以看到下面的示例如何getType();
根据对象(狗,宠物,警犬)类型工作.
假设你有三只狗
狗 - 这是超级班.
宠物狗 - 宠物狗延伸狗.
警犬 - 警犬延伸宠物狗.
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中的所有方法都是虚拟的.这意味着在继承中使用任何方法都可以被覆盖,除非该方法被声明为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();
打印 Normal Dog
obj2.getType();
打印 Pet Dog
obj3.getType();
打印 Police Dog
需要由程序员手动完成向下转换
当您尝试调用哪个方法但secretID();
在obj3
其中PoliceDog object
引用了Dog
哪个是层次结构中的超类时,它会抛出错误,因为obj3
无法访问secretId()
方法.为了调用该方法,您需要手动将obj3向下转换为 PoliceDog
( (PoliceDog)obj3).secretID();
打印 ID
以类似的方式调用类中的dogName();
方法,PetDog
您需要向下转换obj2
为PetDog
obj2被引用,Dog
并且无法访问dogName();
方法
( (PetDog)obj2).dogName();
为什么会这样,这种向上转换是自动的,但是向下转换必须是手动的?嗯,你看,向上转播永远不会失败.但是,如果你有一组不同的狗,并希望他们都垂头丧气到它们的类型,然后有机会的话,其中一些狗实际上是不同类型的,即,PetDog
,PoliceDog
,和过程失败,抛出ClassCastException
.
如果您已将对象引用到超类类型,则需要手动向下转换对象.
注意:这里通过引用意味着当你向下转换它时你没有改变你的对象的内存地址它仍然是相同的你只是在这种情况下将它们分组到特定类型
Dog
Nadeesha Thi.. 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
为什么会这样,这种向上转换是自动的,但是向下转换必须是手动的?嗯,你看,向上转播永远不会失败.但是如果你有一组不同的动物并且想要将它们全部转移到一只猫身上,那么就有机会,这些动物中的一些实际上是狗,并且通过抛出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; }
有关更多信息,请阅读本文
向上转换为超类型,而向下转换则转换为子类型.始终允许向上转换,但是向下转换涉及类型检查并且可以抛出ClassCastException
.
在你的情况下,从a Dog
到a Animal
的强制转换是向上的,因为a Dog
是a Animal
.通常,只要两个类之间存在is-a关系,就可以进行upcast.
向下倾斜会是这样的:
Animal animal = new Dog(); Dog castedDog = (Dog) animal;
基本上你正在做的是告诉你知道什么该对象的运行时类型的编译器真的是.编译器将允许转换,但仍将插入运行时完整性检查以确保转换有意义.在这种情况下,中投可能是因为在运行时animal
实际上是Dog
即使静态类型的animal
是Animal
.
但是,如果你这样做:
Animal animal = new Animal(); Dog notADog = (Dog) animal;
你会得到一个ClassCastException
.原因是因为animal
运行时类型是Animal
,所以当你告诉运行时执行强制转换时,它会发现它animal
不是真的Dog
,所以抛出一个ClassCastException
.
要调用超类的方法,您可以执行super.method()
或执行upcast.
要调用子类的方法,您必须进行向下转换.如上所示,您通常会冒ClassCastException
这样做的风险; 但是,您可以instanceof
在执行强制转换之前使用运算符检查对象的运行时类型,这样可以防止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; }
向下和向上铸造如下:
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
向上转换和向下转换是Java的重要组成部分,它允许我们使用简单的语法构建复杂的程序,并为我们提供了很多优势,例如多态或分组不同的对象.Java允许将子类类型的对象视为任何超类类型的对象.这称为向上转播.向上转换是自动进行的,而向下转换必须由程序员手动完成,我将尽力解释为什么会如此.
向上转换和向下转换不像将原语从一个转换为另一个,我相信当程序员开始学习构建对象时,这会引起很多混乱.
多态性:默认情况下,java中的所有方法都是虚拟的.这意味着在继承中使用任何方法都可以被覆盖,除非该方法被声明为final或static.
您可以看到下面的示例如何getType();
根据对象(狗,宠物,警犬)类型工作.
假设你有三只狗
狗 - 这是超级班.
宠物狗 - 宠物狗延伸狗.
警犬 - 警犬延伸宠物狗.
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中的所有方法都是虚拟的.这意味着在继承中使用任何方法都可以被覆盖,除非该方法被声明为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();
打印 Normal Dog
obj2.getType();
打印 Pet Dog
obj3.getType();
打印 Police Dog
需要由程序员手动完成向下转换
当您尝试调用哪个方法但secretID();
在obj3
其中PoliceDog object
引用了Dog
哪个是层次结构中的超类时,它会抛出错误,因为obj3
无法访问secretId()
方法.为了调用该方法,您需要手动将obj3向下转换为 PoliceDog
( (PoliceDog)obj3).secretID();
打印 ID
以类似的方式调用类中的dogName();
方法,PetDog
您需要向下转换obj2
为PetDog
obj2被引用,Dog
并且无法访问dogName();
方法
( (PetDog)obj2).dogName();
为什么会这样,这种向上转换是自动的,但是向下转换必须是手动的?嗯,你看,向上转播永远不会失败.但是,如果你有一组不同的狗,并希望他们都垂头丧气到它们的类型,然后有机会的话,其中一些狗实际上是不同类型的,即,PetDog
,PoliceDog
,和过程失败,抛出ClassCastException
.
如果您已将对象引用到超类类型,则需要手动向下转换对象.
注意:这里通过引用意味着当你向下转换它时你没有改变你的对象的内存地址它仍然是相同的你只是在这种情况下将它们分组到特定类型
Dog
也许这张桌子有帮助.调用callme()
类Parent
或类的方法Child
.原则上:
UPCASTING - >隐藏
DOWNCASTING - >揭示
很久以前我就知道这个问题,但对于这个问题的新用户.请阅读本文,其中包含有关向上转换,向下转换和使用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
为什么会这样,这种向上转换是自动的,但是向下转换必须是手动的?嗯,你看,向上转播永远不会失败.但是如果你有一组不同的动物并且想要将它们全部转移到一只猫身上,那么就有机会,这些动物中的一些实际上是狗,并且通过抛出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; }
有关更多信息,请阅读本文
最好尝试这种方法进行向上转换,这很容易理解:
/* 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(); } }