对象的转型是面向对象的多态性的体现。
如上三段代码:分别是定义的父类、子类和主函数
这行代码先是声明了一个 Lesson9_son的引用a并调用Lesson9_son构造函数生成了一个Lesson9_son类型的对象赋值给了a;
在子类当中出去继承以上变量和函数以外还有
所以在这个基础上推断,父类对象b是不能调用子类中的变量ch和函数Fun_son()的,因为在父类里面根本就没有这个ch和Fun_son();但是这里问题又出现了,子类和父类里面都有Function函数,存在函数的复写(override)关系。这时候如果写成b.Function();
结果会是什么?经过验证后的结果如下:
上述结果可以看出,父类里面只有第一句打印,子类里面同时有两句打印,这很明显是子类中的函数,这里的变量ch并没有值,是因为父类引用b并不能给ch赋值,主函数开始执行到打印输出并没有给ch赋值。
我先后定义一个子类的对象a,b,先后把他们父类引用A并对变量赋值然后打印,注意这里的A先是指向的a赋值然后打印,然后让A指向b赋值并打印,然后再让A指向a并打印,从结果发现这跟C语言上的指针比较类似。
这里说明一下:对于向上转型,可以直接定义父类引用使用子类的构造函数;
这两个表达的意思是一样的。
转型分为:
对象的向上转型:将子类的对象赋值给父类的引用
对象的向下转型:将父类的对象赋值给子类的引用
1、对象的向上转型
class Lesson9_father{
String str;
int num;
void Function(){
System.out.println("the father_str is " + this.str + ",the father_num is" + this.num);
}
}
class Lesson9_son extends Lesson9_father{
char ch;
void Fun_son(){
}
void Function(){
super.Function();
//System.out.println("the son_str is " + this.str + ",the son_num is" + this.num);
System.out.println("the son_char is " + this.ch );
}
}
class Test{
public static void main(String args []){
Lesson9_son a = new Lesson9_son();
Lesson9_father b = a;
}
}
如上三段代码:分别是定义的父类、子类和主函数
在主函数中首先:
Lesson9_son a = new Lesson9_son();
这行代码先是声明了一个 Lesson9_son的引用a并调用Lesson9_son构造函数生成了一个Lesson9_son类型的对象赋值给了a;
Lesson9_father b = a;
这行代码是声明了一个Lesson9_father类型的引用b并把a赋值给了b;
在内存中的示意图如下:
在JAVA中,一个引用能够调用哪些成员变量和成员函数,取决于这个引用的类型。所以在上述测试代码中:对象b是父类,在父类中只有两个成员变量和一个成员函数:
String str;
int num;
void Function(){
...
}
在子类当中出去继承以上变量和函数以外还有
char ch;//变量
void Fun_son(){//函数
}
所以在这个基础上推断,父类对象b是不能调用子类中的变量ch和函数Fun_son()的,因为在父类里面根本就没有这个ch和Fun_son();但是这里问题又出现了,子类和父类里面都有Function函数,存在函数的复写(override)关系。这时候如果写成b.Function();
Lesson9_son a = new Lesson9_son();
Lesson9_father b = a;
b.str = "abc";
b.num = 123;
b.Function();
结果会是什么?经过验证后的结果如下:
D:\Android\src>javac Lesson9.java
D:\Android\src>javac Test.java
D:\Android\src>java Test
the father_str is abc,the father_num is123
the son_char is
D:\Android\src>
上述结果可以看出,父类里面只有第一句打印,子类里面同时有两句打印,这很明显是子类中的函数,这里的变量ch并没有值,是因为父类引用b并不能给ch赋值,主函数开始执行到打印输出并没有给ch赋值。
这里先把概念写出来:一个引用调用的是哪一个方法,取决于这个引用所指向的对象。
然后再解释:
首先b是a的引用,而a是子类的对象,父类的引用b只是指向的子类引用a所指的对象,所以这个a所调用的成员变量、成员函数实际上都是a的成员变量和成员函数;到此,我还是觉得云里雾里,于是我又写了以下代码测试:
class Test{
public static void main(String args []){
Lesson9_son a = new Lesson9_son();
Lesson9_son b = new Lesson9_son();
a.ch = 'a';
b.ch = 'b';
Lesson9_father A = a;
A.str = "AAA";
A.num = 111;
A.Function();
A = b;
A.str = "BBB";
A.num = 222;
A.Function();
A = a;
A.Function();
}
}
我先后定义一个子类的对象a,b,先后把他们父类引用A并对变量赋值然后打印,注意这里的A先是指向的a赋值然后打印,然后让A指向b赋值并打印,然后再让A指向a并打印,从结果发现这跟C语言上的指针比较类似。
测试结果如下:
D:\Android\src>javac Lesson9.java
D:\Android\src>javac Test.java
D:\Android\src>java Test
the father_str is AAA,the father_num is111
the son_char is a
the father_str is BBB,the father_num is222
the son_char is b
the father_str is AAA,the father_num is111
the son_char is a
D:\Android\src>
这里说明一下:对于向上转型,可以直接定义父类引用使用子类的构造函数;
例如:
Lesson9_son a = new Lesson9_son();
Lesson9_father A = a;
和
Lesson9_father A = new Lesson9_son();
这两个表达的意思是一样的。
/*******************************************************华丽分割线***********************************************************/
2、对象的向下转型
如:
Lesson9_son a = Lesson9_son();
Lesson9_father A=a;
Lesson9_son b = (Lesson9_son)A;
小结:
1.向下转型的前提是向上转型;
2.在向下转型的时候加上强制转换,(Lesson9_son)A中的Lesson9_son就是强制转换的体现;
3.直接生成的父类对象是无法转型到子类的类型的;
By Urien 2017年8月29日 19:46:43