-
对象类型转换
2020-03-26 15:49:55对象类型转换 与基本数据类型的相互转换一样,对象的类型转换可通过自动转换或强制转换进行。 一、 无继承关系的两个类的对象之间 不能相互转换。试图转换时出现编译错误(Cannot convert “A” to “B”) 二、 有...对象类型转换
与基本数据类型的相互转换一样,对象的类型转换可通过自动转换或强制转换进行。
一、 无继承关系的两个类的对象之间
不能相互转换。试图转换时出现编译错误(Cannot convert “A” to “B”)
二、 有继承关系的两个类的对象之间- 子类的对象转换为父类的对象:
可自动转换,当然也可以强制转换。 - 父类的对象转换为子类的对象:
分两种情况:
由new语句创建的父类对象不能转换为子类的对象,试图自动转换时出现编译错误(Cannot implicitly convert…),试图强制转换时出现运行错误(ClassCastException)。
由子类对象转化得到的父类对象可以强制转换为同类型的子类对象,但试图自动转换时会出现编译错误(Cannot implicitly convert…)。
- 子类的对象转换为父类的对象:
-
Java对象类型转换和强制对象类型转换
2019-09-11 23:47:14Java语言允许某个类型的引用变量引用子类的实例,而且...例如,Creature 类表示生物类,Animal 类表示动物类,该类对应的子类有 Dog 类,使用对象类型表示如下: Animal animal=new Dog(); Dogdog=(Dog)animal; ...Java 语言允许某个类型的引用变量引用子类的实例,而且可以对这个引用变量进行类型转换。如果把引用类型转换为子类类型,则称为向下转型;如果把引用类型转换为父类类型,则称为向上转型。
例如,Creature 类表示生物类,Animal 类表示动物类,该类对应的子类有 Dog 类,使用对象类型表示如下:Animal animal=new Dog(); Dogdog=(Dog)animal; //向下转型,把Animal类型转换为Dog类型 Creature creature=animal; //向上转型,把Animal类型转换为Creature类型
例 1
下面通过具体的示例演示对象类型的转换。例如,父类 Animal 和子类 Cat 中都定义了实例变量 name、静态变量 staticName、实例方法 eat() 和静态方法 staticEat()。此外,子类 Cat 中还定义了实例变量 str 和实例方法 dogMethod()。
父类 Animal 的代码如下:public class Animal { public String name="Animal:动物"; public static String staticName="Animal:可爱的动物"; public void eat() { System.out.println("Animal:吃饭"); } public static void staticEat() { System.out.println("Animal:动物在吃饭"); } }
子类 Cat 的代码如下:public class Cat extends Animal { public String name="Cat:猫"; public String str="Cat:可爱的小猫"; public static String staticName="Dog:我是喵星人"; public void eat() { System.out.println("Cat:吃饭"); } public static void staticEat() { System.out.println("Cat:猫在吃饭"); } public void eatMethod() { System.out.println("Cat:猫喜欢吃鱼"); } public static void main(String[] args) { Animal animal=new Cat(); Cat cat=(Cat)animal; //向下转型 System.out.println(animal.name); //输出Animal类的name变量 System.out.println(animal.staticName); // 输出Animal类的staticName变量 animal.eat(); //输出Cat类的eat()方法 animal.staticEat(); //输出Animal类的staticEat()方法 System.out.println(cat.str); //调用Cat类的str变量 cat.eatMethod(); //调用Cat类的eatMethod()方法 } }
通过引用类型变量来访问所引用对象的属性和方法时,Java 虚拟机将采用以下绑定规则:
- 实例方法与引用变量实际引用的对象的方法进行绑定,这种绑定属于动态绑定,因为是在运行时由 Java 虚拟机动态决定的。例如,animal.eat() 是将 eat() 方法与 Cat 类绑定。
- 静态方法与引用变量所声明的类型的方法绑定,这种绑定属于静态绑定,因为是在编译阶段已经做了绑定。例如,animal.staticEat() 是将 staticEat() 方法与 Animal 类进行绑定。
- 成员变量(包括静态变量和实例变量)与引用变量所声明的类型的成员变量绑定,这种绑定属于静态绑定,因为在编译阶段已经做了绑定。例如, animal.name 和 animal.staticName 都是与 Animal 类进行绑定。
对于 Cat 类,运行时将会输出如下结果:
Animal:动物 Animal:可爱的动物 Cat:吃饭 Animal:动物在吃饭 Cat:可爱的小猫 Cat:猫喜欢吃鱼
强制对象类型转换
Java 编译器允许在具有直接或间接继承关系的类之间进行类型转换。对于向下转型,必须进行强制类型转换;对于向上转型,不必使用强制类型转换。
- 例如,对于一个引用类型的变量,Java 编译器按照它声明的类型来处理。如果使用 animal 调用 str 和 eatMethod() 方法将会出错,如下:
animal.str=""; //编译出错,提示Animal类中没有str属性
animal.eatMethod(); //编译出错,提示Animal类中没有eatMethod()方法
- 如果要访问 Cat 类的成员,必须通过强制类型转换,如下:
((Cat)animal).str=""; //编译成功
((Cat)animal).eatMethod(); //编译成功
- 把 Animal 对象类型强制转换为 Cat 对象类型,这时上面两句编译成功。对于如下语句,由于使用了强制类型转换,所以也会编译成功,例如:
Cat cat=(Cat)animal; //编译成功,将Animal对象类型强制转换为Cat对象类型
- 子类的对象可以转换成父类类型,而父类的对象实际上无法转换为子类类型。因为通俗地讲,父类拥有的成员子类肯定也有,而子类拥有的成员,父类不一定有。因此,对于向上转型,不必使用强制类型转换。例如:
Cat cat=new Cat();
Animal animal=cat; //向上转型,不必使用强制类型转换
- 如果两种类型之间没有继承关系,那么将不允许进行类型转换。例如:
Dog dog=new Dog();
Cat cat=(Cat)dog; //编译出错,不允许把Dog对象类型转换为Cat对象类型
-
C# 对象类型转换
2016-08-03 17:24:36C# 对象类型转换在日常开发时,经常需要将对象从一种类型转换为另一种类型。CLR允许将对象转换为它的(实际)类型或者它的任何基类型。
C#不要求任何特殊语法即可将对象转换为它的任何基类型,因为向基类型的转换被认为是一种安全的隐式转换。然而,将对象转换为它的某个派生类型时,C#要求开发人员只能进行显式转换,因为这种转换可能在运行时失败。可以理解为:父类强制转换成子类,子类隐式转换成父类
internal class Employee { } class Program { static void Main(string[] args) { // 子类隐式转换成父类,不需要转换 // 因为new返回一个Employee对象,而Object是Employee的基类 Object o = new Employee(); // 子类可以自动转父类 可以这么理解把子类的实例em的地址赋值给了o1, o1的地址就是em的地址 // 这时就可以调用Employee 类的方法,点出Employee 类的属性 Employee em = new Employee(); Object o1 = em; // 父类强制转换成子类, 需要转换 // 因为Employee派生自Object Employee e = (Employee)o; } }
在运行时,CLR会检查转型操作,确定总是转换为对象得实际类型或者它的任意类型。下面的代码虽然能通过编译,但会在运行时抛出InvalidCastException异常:
internal class People { } internal class Employee : People { } internal class Manager : Employee { } class Program { static void Main(string[] args) { // 创建实例的时候没有将父类引用到子类对象,是无法转换的 // PromoteEmployee不能运行成功 People p = new People(); PromoteEmployee(p); // 创建实例的时候将父类引用到子类对象,是可以转换的 // PromoteEmployee能运行成功 People p1 = new Employee(); PromoteEmployee(p1); // Manager"属于"(IS-A)Employee对象 // PromoteEmployee能运行成功 Manager m = new Manager(); PromoteEmployee(m); // DateTime不是从Employee派生的 // PromoteEmployee不能运行成功 DateTime newYears = new DateTime(2011, 10, 1); PromoteEmployee(newYears); } static void PromoteEmployee(Object o) { // 编译器在编译时无法准确地获知对象0引用的是什么类型,因此允许代码通过编译 // 但在运行时,CLR知道了o引用的是什么类型(在每次执行转型的时候) // 所以它会核实对象的类型是不是Employee或者从Employee派生的任何类型 Employee e = (Employee)o; } }
使用C#的is和as操作符来转型
在C#语言中进行转换的另一种方式是使用is操作符。is检查对象是否兼容于指定类型,返回Boolean值true或false。注意,is操作符永远不抛出异常,例如以下代码:static void Main(string[] args) { Object o = new Object(); Boolean b1 = (o is Object); //True Boolean b2 = (o is Employee); //False Boolean b3 = (o is Nullable); //False }
is操作符通常像下面这样使用:
static void Main(string[] args) { Object o = new Employee(); if( o is Employee ) { Employee e = (Employee)o; } }
在上诉代码中,CLR实际检查两次对象类型。is操作符首先核实o是否兼容于Employee类型。如果是,在if语句内部转型时,CLR再次核实o是否引用一个Employee。CLR的类型检查增强了安全性,但无疑会对性能造成一定的影响。这是因为CLR首先必须判断变量(o)引用的对象的实际类型。然后CLR必须遍历继承层次结构,用每个基类型去核对指定的类型(Employee)。由于这是一个相当常用的编程模式,所以C#专门提供了as操作符,目的就是简化这种代码的写法,同时提升其性能。
static void Main(string[] args) { Object o = new Employee(); Employee e = o as Employee; if(e != null) { } }
在这段代码中,CLR核实o是否兼容于Employee类型;如果是,as放回对同一个对象的非null引用。如果o不兼容于Employee类型,as返回null。as操作符永远不抛出异常。注意,as操作符造成CLR只校验一次对象类型。if语句只检查e是否为NULL;这个检查的速度不校验对象的类型快得多。
测试代码:
namespace ConsoleApplicationTest { internal class B{} internal class D : B{} class Program { static void Main(string[] args) { Object o1 = new Object(); //OK Object o2 = new B(); //OK Object o3 = new D(); //OK Object o4 = o3; //OK B b1 = new B(); //OK B b2 = new D(); //OK D d1 = new D(); //OK B b3 = new Object(); //编译时错误,正确:Object b3 = new B(); D d2 = new Object(); //编译时错误,正确:Object b3 = new D(); B b4 = d1; //OK,子类可以自动转父类 D d3 = b2; //编译时错误,正确:D d3 = (D)b2; D d4 = (D)d1; //OK D d5 = (D)b2; //OK D d6 = (D)b1; //运行时错误,创建实例的时候没有将父类引用到子类对象 B b5 = (B)o1; //运行时错误,创建实例的时候没有将父类引用到子类对象 B b6 = (D)b2; //OK,创建实例的时候将父类引用到子类对象 } } }
-
java中对象类型转换
2014-10-19 14:49:27java对象类型转换 java对象类型转换,当对不具有相同类型的对象进行强制类型转换时,java运行时将抛出java.lang.ClassCastException的错误,这不单单是java不允许这样做,任何一种面向对象德开发语言都不允许的...java对象类型转换
java对象类型转换,当对不具有相同类型的对象进行强制类型转换时,java运行时将抛出java.lang.ClassCastException的错误,这不单单是java不允许这样做,任何一种面向对象德开发语言都不允许的类型转换。所以今天只讨论对象继承关系下的向上转型和向下转型问题。
java中向上、向下转型并不是什么高人定义的数据,它的命名原因跟象形文字的来源差不多,原因在于很早以前我们在设置类图时,总是习惯将父类放在上面,子类放在下面,然后通过一条父子连接线连接,就是这样从感官的角度 将子类向父类转换称之为“向上转型” 反之,为“向下转型”。
在java开发中我们经常见到的为了降低程序间的耦合度,在定义某些类是通常使用的都是父类型,之后程序调用者就可以根据自己的需求将子类型赋值上去,实现功能上的调用,在这过程中就是运用了对象的向上转型,运行时通过后期绑定来实现对实际子类的调用。这样就实现了传说中java的多态功能。然而有些时候为了完成某些父类没有的功能,我们需要将向上转型后的父类再转成子类,实现其他的处理,这就是我们的向下转型。在这里,一定要切记一点在进行向下转型前一定要判断是否类型相同(isAssignFrom或instanceof),否则将抛出java.lang.ClassCastException的错误。
这时候有人可能会有很多的误解(我也曾经被弄糊涂了),都说子类继承了父类,那么父子类之间具有相同的类型那么为什么不能够直接进行向下转型呢??? 原因在于 子类继承父类是对父类所提供的服务接口的一个扩展,也就是说 父类提供的接口是子类所提供接口的一个子集,所以说单纯的父类对象时无法转型某个子类对象的。
SuperClass super = new SuperClass;//创建父类对象
SonClass son = (SonClass)super; //这样的操作时完全错误的
我们可以再设计一下父类和子类的类结构:
SuperClass{
public void printA(){System.out.println("Super printA");}
}
SonClass extends SuperClass{
public void printA(){System.out.println("Son printA")} //对父类的一个覆写
public void printB(){System.out.println("Son PrintB")} //对父类的一个扩展接口
}
这个时候我们强制将父类对象向下转换成子类对象时,父类对象中没有printB()方法,这样就会造成混乱,所以在进行向下转型时一定要先判断父类的类型。
转自:http://blog.chinaunix.net/uid-26863299-id-3527156.html -
c++中什么是对象类型转换
2015-06-11 08:46:30c++中什么是对象类型转换?什么是向上转换和向下转换?具体应该要怎么做,可以举个与多态结合的例子吗? -
Swift 对象类型转换
2015-08-28 15:13:57Swift 中对象是可以转换的,应为面向对象就会涉及继承,子类,父类等等 有几点规则我们先说一下 子类对象可以直接转换为父类对象的 父类对象可以有条件的转换为子类对象,这个我们下边在讲 首先我们创建三个类 人 ... -
Java对象类型转换的四个经验
2010-01-25 10:53:00Java对象类型转换时Java开发中经常遇到的,本文向您介绍Java对象类型转换的一些技巧和注意事项,包括向上转型与向下转型都操作和主要点。 一、向上转型与向下转型。 对象类型的转换在Java语言平台中经常遇到,主要... -
Java —— 对象类型转换和instanceof函数
2017-03-20 17:19:23* 而一个父类对象类型一般是不能转换为子类对象使用的。因为子类继承与父类,所以说子类中的 * 一些数据成员和方法父类中未必会有,但如果是一个父类对象引用实际引用的是一个子类对象, * 则可以强制将这个父类... -
Struts2的自定义页面提交对象类型转换
2016-11-29 22:58:19Struts2能自动的将页面表单提交的字符串类型转换成八种基本类型,或者Date类型、String类型等,而自定义类型的转换则可以自己通过代码显式的设定进行转换。 1.新建完成类型转换类,继承DefaultTypeConverter类 -
Qt中的对象类型转换
2015-12-18 22:59:05char * 与 const char *的转换 char *ch1="hello11"; const char *ch2="hello22"; ch2 = ch1;//不报错,但有警告 ch1 = (char *)ch2;char 与 QString的转换char 转换为 QString 其实方法有很多中,我用的是:char a... -
java 对象类型转换之父对象转化为子对象
2014-08-07 20:11:07简单理一下上面的类型转换过程:在第二个callA()方法时,传递给该方法的是一个B类型的对象。由于callA函数所接收的是一个A类型的对象,所以这里进行了一次类型转化(子类型对象转换为父类型对象)。接下来到了if... -
DLL对象类型转换
2009-05-12 11:42:00以下案例代码为在dll中创建一个adodataset对象,并把它返回给主调函数 //以下代码是错误的!!!//这一节主要告诉大家,以这种方式进行开发dll是不对的以及错误原因,正确的方式是什么!//DLL内创建对象,并把对象...
-
c1任务学习感受
-
图标编辑工具IcoFX v3.5.1.0
-
MySQL 高可用工具 DRBD 实战部署详解
-
MySQL 高可用工具 heartbeat 实战部署详解
-
基于python的dango框架购物商城毕业设计毕设源代码使用教程
-
leetcode 704 暨 二分查找左闭右闭模板
-
基于THB7128步进电机驱动板protel99se设计硬件原理图+PCB源文件(直接拿来可以用).zip
-
自动记录剪贴数据 Clipore
-
GX Works2 安装包仅用于学习!
-
Linux系统安装教程.pdf
-
【Python-随到随学】 FLask第一周
-
vue3从0到1-超详细
-
matplotlib应用实例
-
LeetCode 59. 螺旋矩阵 II (枚举、细节)
-
26-30份商业计划书.zip
-
NetSetMan v5.0.5特别版
-
贴片STC最小系统资料包v3.4.rar
-
C++基础篇
-
Mysql联结表
-
Altera(Intel)_Cyclone_IV_EP4CE15核心板+开发底板PDF原理图+Quartus逻辑例程+开发板文档资料.zip