------------------------------------------------------------------------------------------------------------------------------------
第(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)一般不可以,但是如果此父类已经指向了此子类对象,可以
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 + "]";
}
}
}
结果:
son:1407343478
SonClazz [car=benz, watch=null]
par:1407343478
李四
20
null
SonClazz [car=benz, watch=null]
结论:
子类强制转换为父类对象时,并没有实际丢失它原有内存空间(比父类多的那些部分)
只是暂时不可访问,所以能再转回来。
对比son:1407343478,par:1407343478也可以看出
子类实例转化为父类实例后 是否还从属(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; 测试以上三个实例能否访问子类新定义的成员变量,重写的方法,新定义的方法
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)父类或子类么?测试结果为既属于父类实例,也属于子类实例
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)子类的实例呢?
Father father = new Father(1);
if(father instanceof Son){
System.out.println("父类实例竟然属于自己的子类?No不属于");
}else{
System.out.println("什么也没发生");
}
得到结果:
什么也没发生 所以new得到的父类实例不属于自己的子类,子类实例必然属于父类(这点就不用证明了,任何类对象都属于object)