一、今日学习内容
1、多态变化
(1)Java中多态的实现
Java中多态的体现具体表现在方法的重载和覆盖上,覆盖的概念,主要是指子类重写了父类中的方法。
示例:子类重写父类中的方法
public class Father{ public void say() { System. out.println("father say()"); } } class Son extends Father{ public void say(){ System. out.println("son say()"); } }
子类重写父类中的方法,即子类中的方法与父类中的方法保持一致。 但是方法的修饰符一定要大于等于父类中方法的修饰符。
此时在子类中调用与父类相同的方法时,则调用的是子类的,并非父类的方法。
public class Father{ public void say() { System.out.println("father say()"); } public static void main (String[] args) { Son son=new Son() ; son.say() ; } } class Son extends Father{ public void say() { System.out.println("son say()") ; } }
输出结果:son say()
(2)类型检测——向上转型/向下转型
向上转型是指父类对象的引用指向子类对象。向下转型是指在向上转型的基础上再次指向子类的对象。
a.向上转型:父类 对象=new 子类()
示例:向上转型
public class Father{ public void say() { System. out.println("father say()"); } public static void main(String[] args) { //向上转型 Father son = new Son() ; son. say(); } } class Son extends Father{ public void say() { System. out.println("son say()"); } }
输出结果: son say()
但是有时使用向上转型会丢失掉子类特有的方法,例如:
public class Father{ public void say() { System. out. println("father say()") ; } public static void main(String[] args) { //向上转型 Father son= new Son() ; / /报错! son. sayMe () ; } } class Son extends Father{ public void say() { System.out.println("son say()"); } public void sayMe () { System. out.println("son sayMe()") ; } }
会在编译时报错!
b.向下转型:父类 对象1 = new 子类();
子类 对象2=(子类)对象1;
从这个格式可以看出,使用向下转型必须使用(类型)进行强转。
示例:向下转型
public class Father{ public void say() { System. out.println("father say()"); } public static void main(String[] args) { //向上转型 Father son= new Son() ; //向下转型 Son son2 =(Son) son; son2.sayMe () ; } } class Son extends Father { public void say() { System. out.println("son say()"); } public void sayMe () { System. out.printin("son sayMe()") ; } }
注:如果直接将父类强转成子类对象会报错! 例:
虽然在编译时没有错,但是在运行时会报错。
这是因为父类对象不能直接强转成子类对象。在实际开发中,凡是用到继承,我们应该会第一想到使用向上类型转换。
现将向上转型总结如下。
(1)父类引用指向子类对象,子类引用不能指向父类对象。
(2)把子类对象直接赋给父类引用叫upcasting 向上转型,向.上转型不用强制转型,如Father f1 =new Son()。
(3)把指向子类对象的父类引用赋给子类引用叫向下转型( downcasting),要强制转型。如fl就是一个指向子类对象的父类引用,把fl赋给子类引用s1即 Son s1= (Son) fl。其中,fl 前面的(Son)必须添加,进行强制转换。
(4) upcasting 会丢失子类特有的方法(下面有说明),但是子类overriding 父类的方法,子类方法有效。
(3)动态绑定
Java虚拟机调用一个类方法时,它会基于对象引用的类型(通常在编译时可知)来选择所调用的方法。相反,当虚拟机调用一个实例方法时,它会基于对象实际的类 型(只能在运行时得知)来选择所调用的方法,这就是动态绑定,是多态的一种。动态绑定为解决实际的业务问题提供了很大的灵活性,是-种非常优美的机制。
动态绑定具体表现在向上转型上,因为只有在运行时才知道具体运行的是哪个实例。
示例:动态绑定
public class Father { public void say() { System. out.println("father say()") ; } public static void main(String[] args) { //向上转型 Father son = new Son() ; son.say() ; } } class Son extends Father { public void say() { System.out.println("son say()"); } }
静态绑定:所谓静态绑定就是在程序编译时就绑定的,在Java中的变量都是静态绑定的,只有private、 static和final是静态绑定的。
public class Father { String name=" father"; public static void say() { System. out.println("father say()"); } public void say2() { System. out.printin("father say2()"); } public static void main (String[] args) { Father f = new Son() ; //虽然是指向了Son的引用,但是变量在编译的时候就动态绑定了 //所以输出的是father System. out. println(f.name) ; / /因为Father里面的say是static, / /编译时就静态绑定了,所以输出father say() f.say() ; //而say2不是static方法,f是由Son new 出来的, //执行的时候会执行new它的那个类的say2()方法, //所以输出son say2(), 这是java的多态性 f.say2() ; } } class Son extends Father { String name="son"; public static void say() { System. out.println("son say()"); } public void say2() { System. out.println("son say2()"); } }
输出结果:father
father say()
son say2()
二、遇到的问题
对向下转型不是很理解
三、明日计划
明天继续学习第五章的内容