前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >探讨Java中的父子类转化问题

探讨Java中的父子类转化问题

作者头像
用户6182664
发布2020-05-07 15:52:21
4.1K0
发布2020-05-07 15:52:21
举报
文章被收录于专栏:Java程序员那些事
有两个问题:
(1)子类对象可以转化为父类对象吗?
(2)父类对象可以转化为子类对象吗?

------------------------------------------------------------------------------------------------------------------------------------

第(1)个问题应该都不陌生,也没什么好探讨的,肯定可以,因为在多态中经常用到。

如:class Father{}

calss Son extends publc Father{}

Father f = new Son(); //父类引用指向子类对象

其中,new Son()表示在在堆中分配了一段空间来存放类Son中的数据,

并返回一个Son的对象,并赋值给Father的引用f,即f指向子类的对象,

此时,子类的对象并没有定义一个名字。

定价于:

Son s = new Son();

Father f = s;

------------------------------------------------------------------------------------------------------------------------------------

第(2)个问题:一般情况下,父类对象是不可以强制转化为子类对象的,

如:

class Father{}

calss Son : publc Father{}

Son s = new Father(); //error

因为,子类除了从父类继承一些东西外,它还增加了一些自己的东西,也就是说,

子类对象一般都比父类对象包含更多的东西。这样的话,子类如果访问子类新增的内容,

而这些内容父类并没有,所以就会报错。

但是,如果前提是:此父类对象已经指向了此子类对象,就可以转换。

如:

Father f = new Son(); //父类引用指向子类对象

Son s2 = (Son)f; //可以

因为,子类强制转换为父类对象时,并没有实际丢失它原有内存空间(比父类多的那些部分)

只是暂时不可访问,所以能再转回来。

一般在前面加一条判断语句 if(father instanceof Son);防止报ClassCastExcept异常。

如:

Father f = new Son(); //父类引用指向子类对象

if(father instanceof Son){ Son s2 = (Son)f;}

结论:(1)子类对象可以转化为父类对象

(2)一般不可以,但是如果此父类已经指向了此子类对象,可以

代码语言:javascript
复制
package com.jesper.seckill.clazzConvert;

public class ClazzConvertTest {

	public static void main(String[] args) {
		ClazzConvertTest testObj = new ClazzConvertTest();
		ClazzConvertTest.SonClazz son = testObj.new SonClazz();
		son.setName("李四");
		son.setAge(20);
		son.setCar("benz");
		System.out.println("son:"+son.hashCode());
		System.out.println(son.toString());
		ParentClazz par = son;
		System.out.println("par:"+par.hashCode());
		System.out.println(par.getName());
		System.out.println(par.getAge());
		System.out.println(par.getMoney());
		SonClazz son2 = (SonClazz) par;
		System.out.println(son2);
		
		System.out.println("--------------");
		ParentClazz parent = testObj.new ParentClazz();
		parent.setMoney(100000000.00);
		ClazzConvertTest.SonClazz sonExt = (SonClazz) parent;
		System.out.println(sonExt.getMoney());
	}

	class SonClazz extends ParentClazz {
		private String car;
		private String watch;
		public String getCar() {
			return car;
		}
		public void setCar(String car) {
			this.car = car;
		}
		public String getWatch() {
			return watch;
		}
		public void setWatch(String watch) {
			this.watch = watch;
		}
		@Override
		public String toString() {
			return "SonClazz [car=" + car + ", watch=" + watch + "]";
		}
	}
	
	class ParentClazz {
		private String name;
		private Double money;
		private Integer age;
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public Double getMoney() {
			return money;
		}
		public void setMoney(Double money) {
			this.money = money;
		}
		public Integer getAge() {
			return age;
		}
		public void setAge(Integer age) {
			this.age = age;
		}
		@Override
		public String toString() {
			return "ParentClazz [name=" + name + ", money=" + money + ", age="
					+ age + "]";
		}
	}
}

结果:

代码语言:javascript
复制
son:1407343478
SonClazz [car=benz, watch=null]
par:1407343478
李四
20
null
SonClazz [car=benz, watch=null]

结论:

子类强制转换为父类对象时,并没有实际丢失它原有内存空间(比父类多的那些部分)

只是暂时不可访问,所以能再转回来。

对比son:1407343478,par:1407343478也可以看出

2、java父子类实例强制转化后 各实例之间的关系

子类实例转化为父类实例后 是否还从属(instanceof)于子类?

这个被转化得来的父类实例是否能访问子类重写的方法、子类新添加的方法、子类新添加的成员属性、是否还能转化为子类实例?以下测试:

创建一个父类和一个子类,父类拥有成员变量a、方法fun(),子类拥有继承的成员变量a、新定义的成员变量b、重写的方法fun()、新定义的方法fun2()

class Father { public int a; public Father(int a){ this.a = a; } public Father(){ } public void fun(){ System.out.println("父类方法fun已经执行"); } }

class Son extends Father { public int b;//b为子类新增加的成员变量 public Son (int a,int c){ super(a); this.b = c; } public void fun(){ System.out.println("子类重写父类方法fun已经执行"); } public void fun2(){ System.out.println("子类新增加的方法fun2已经执行"); } } 再main函数创建子类实例s,强制转化为f,再把f强制转化为s1

Son s = new Son(1, 2); Father f = (Father)s; Son s1 = (Son)f; 测试以上三个实例能否访问子类新定义的成员变量,重写的方法,新定义的方法

代码语言:javascript
复制
	System.out.println(s.b);

// System.out.println(f.b);子类转换为父类就不能访问子类自定义的属性了 System.out.println(s1.b);//但是再强转回来子类原本的自定义属性和方法又“失而复得” s.fun(); f.fun(); s1.fun(); // f.fun2();子类转换为父类就不能访问子类自定义的方法了 s1.fun2();//但是再强转回来子类原本的自定义属性和方法又“失而复得” 得到如下结果

2 2 子类重写父类方法fun已经执行 子类重写父类方法fun已经执行 子类重写父类方法fun已经执行 子类新增加的方法fun2已经执行 说明:子类转化为父类实例后,这个实例就不能访问子类新增加的成员变量和新增加成员方法了,值得一提的是,这个父类实例虽然被转换为一个父类实例,但调用重写方法,执行的仍是子类重写过的内容。

但是再由这个父类实例转换为子类实例,则这个子类实例s1和之前初始化的子类实例s没有区别,不会因为转换过程而丢失成员变量和成员方法

那么,这三个实例属于(instanceof)父类或子类么?测试结果为既属于父类实例,也属于子类实例

代码语言:javascript
复制
	if(s instanceof Father){
		System.out.println("子类的实例s 属于父类实例");
	}
	if(f instanceof Father){
		System.out.println("父类的实例f 属于父类实例");
	}
	if(s1 instanceof Father){
		System.out.println("子类的实例s1  属于父类实例");
	}
	if(s instanceof Son){
		System.out.println("子类的实例s 属于子类实例");
	}
	if(f instanceof Son){
		System.out.println("父类的实例f 属于子类实例");
	}
	if(s1 instanceof Son){
		System.out.println("子类的实例s1  属于子类实例");
	}

结果:

子类的实例s 属于父类实例 父类的实例f 属于父类实例 子类的实例s1 属于父类实例 子类的实例s 属于子类实例 父类的实例f 属于子类实例 子类的实例s1 属于子类实例 再那么,普通new出的父类实例是不是也属于(instanceof)子类的实例呢?

代码语言:javascript
复制
	Father father = new Father(1);
	if(father instanceof Son){
		System.out.println("父类实例竟然属于自己的子类?No不属于");
	}else{
		System.out.println("什么也没发生");
	}

得到结果:

什么也没发生 所以new得到的父类实例不属于自己的子类,子类实例必然属于父类(这点就不用证明了,任何类对象都属于object)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java程序员那些事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2、java父子类实例强制转化后 各实例之间的关系
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档