1.1为什么使用多态,此为没有使用多态的情况
package Polymorphism; /** * @author zhao xuke * *1.继承、重写、父类的引用指向子类 *2.编译时类型(一般是个父类)由声明时的类型决定 *3.运行时类型(运行时具体是哪个子类就是哪个子类) 由实际对应对象类型决定 *4.多态情况下父类的引用不能指向子类特有的成员变量(或成员函数)强制类型转换后可以指向子类对象 *5.数据类型的转换 ; * 5.1.基本数据类型的转换 * 自动类型转换; 小数据类型 转为 大数据类型 int->float * 强制类型转换: 大数据类型 转为 小数据类型 float->int * 5.2.引用(系统)数据类型转换 * 自动类型转换: 小数据类型 转为 大数据类型 子类->父类 Father f = new Son(); * 强制类型转换: 大数据类型 转为 小数据类型 父类->子类 Father f = new Son(); Son s = (Son)f;如果这 * 不强转就会与要点4矛盾,并抛出ClassCastException表示强转类型转换失败 *6.1 注意: 引用数据类型的转换是建立继承的基础上,如果两个类没有继承关系,那么强转的话会报错 *6.2 进行强制类型的转换(父类->子类 即 Son s = (son)f;)之前父类的引用已经指向了子类 *7.父类的引用指向子类的对象情况有 * 1. 父类对象做形参子类对象做实参 * 2. Father f = new Son(); * Son s = (Son)f; * * 3. Son s = new Son(); * Father f = s; * son s1 =(Son)f; * 4. Father f = new Father(); * Son s = new Son(); * f = s; // 此为父类的引用指向子类的对象 * Son s1 = (son)f; * * 2018年4月12日 - 下午1:26:29 */ public class Animal { public void printVoice(){ System.out.println("动物的叫声"); } } class Dog extends Animal{ public void printVoice(){ System.out.println("旺旺"); } } class Cat extends Animal{ public void printVoice(){ System.out.println("喵喵"); } } class Pig extends Animal{ public void printVoice(){ System.out.println("哼哼"); } }
package Polymorphism; /** * @author zhao xuke * * 2018年4月12日 - 下午1:29:28 */ public class Test { public static void testPrintVoice(Dog d){ d.printVoice(); } public static void testPrintVoice(Cat c){ c.printVoice(); } public static void testPrintVoice(Pig p){ p.printVoice(); } public static void main(String[] args) { Dog d = new Dog(); testPrintVoice(d); Cat c = new Cat(); testPrintVoice(c); Pig p = new Pig(); testPrintVoice(p); } }
运行结果:
旺旺
喵喵
哼哼
1.2.使用多态的情况是这样
package Polymorphism1; /** * @author zhao xuke * * 2018年4月13日 - 下午5:56:28 */ public class Animal { public void printVoice(){ System.out.println("动物的叫声"); } } class Dog extends Animal{ public void printVoice(){ System.out.println("旺旺"); } } class Cat extends Animal{ public void printVoice(){ System.out.println("喵喵"); } } class Pig extends Animal{ public void printVoice(){ System.out.println("哼哼"); } }
package Polymorphism1; /** * @author zhao xuke * * 2018年4月13日 - 下午5:59:11 */ public class Test { public static void testPrintVoice(Animal a){ //编译时多态(父类对象做形参子类对象做实参) a.printVoice(); //发现Animal类中又printVoice()方法 唉通过编译 } public static void main(String[] args) { Animal c= new Cat();//父类的引用指向子类的对象 testPrintVoice(c); Animal d= new Dog();//父类的引用指向子类的对象 testPrintVoice(d); Animal p = new Pig(); testPrintVoice(p); /*Cat x = new Cat(); Animal a = x; //父类的引用指向子类的对象 testPrintVoice(a);*/ } }
运行结果:
喵喵
旺旺
哼哼
总结:用了多态后父类对象做形参子类对象做实参减少了代码量。
2.1.多态例子练习多态情况下父类的引用不能指向子类特有的成员变量(或成员函数)强制类型转换后可以指向子类对象这时候就需要强制类型转换
package Polymorphism2; /** * @author zhao xuke * * 2018年4月12日 - 下午3:34:52 */ public class Animal { public void printVoice(){ System.out.println("动物的叫声"); } } class Dog extends Animal{ public void printVoice(){ System.out.println("旺旺"); } public void printRole(){ System.out.println("看大门"); } } class Cat extends Animal{ public void printVoice(){ System.out.println("喵喵"); } public void printRole(){ System.out.println("捉老鼠"); } } class Pig extends Animal{ public void printVoice(){ System.out.println("哼哼"); } }
package Polymorphism2; /** * @author zhao xuke *1.子类的对象可以个被当做父类的对象来使用 *2.子类对象能赋值给父类的变量例如Animal a = new Cat(); * Animal a = new Animal(); * Dog d = new Dog(); * a = d ; * Dog d2 = a;是错的。 * Dog d2 = (Dog)a;这样就对了(如果没有上面的 a = b;语句,就错了) * *2-1.但父类对象不能赋值给子类对象如 Animal a = new Animal(); Dog d = a; 系统会报错 *3.java对象变量是多态的,它们能保存不止一种类型的变量,它们能保存的是声明类型的对象,或是声明类型的子类的对象 *4.向上造型(Cast) *5.String s = "hello"; s = "bay"; s 原来存的是"hello"的地址即s指向"hello",然后s存的是"bay"的地址即s指向"bay" * *6.静态绑定。根据变量的声明类型决定 *7.动态绑定。根据变量的动态类型来决定 *8.在成员函数中调用其他成员函数是通过this * * 2018年4月12日 - 下午3:41:07 */ public class Test { public static void testPrintVoice(Animal a){//编译时多态(父类对象变量做形参子对象变量类做实参) a.printVoice();//发现Animal类中又printVoice()方法 唉通过编译 if(a instanceof Cat){ ((Cat) a).printRole(); } if(a instanceof Dog){ ((Dog)a).printRole(); } } public static void main(String[] args) { Animal c = new Cat(); testPrintVoice(c); /*Cat c = new Cat(); Animal a = c; testPrintVoice(c); */ Animal d = new Dog(); testPrintVoice(d); Animal p = new Pig(); testPrintVoice(p); Cat a2 =(Cat)c;//多态情况下父类的引用不能使用调用子类特有的成员函数需要强制类型转换 a2.printRole(); Dog d2=(Dog)d;//多态情况下父类的引用不能使用调用子类特有的成员函数需要强制类型转换 d2.printRole(); } }
运行结果:
旺旺
看大门
哼哼
捉老鼠
看大门
3.1多态内存分析
package 多态内存分析图代码; /** * @author zhao xuke * * 2018年4月13日 - 上午10:18:14 */ public class Animal { public void printVoice(){ System.out.println("动物的叫声"); } } class Cat extends Animal{ public void printVoice(){ System.out.println("喵喵"); } public void printRole(){ System.out.println("捉老鼠"); } }
package 多态内存分析图代码; /** * @author zhao xuke * * 2018年4月13日 - 上午10:45:41 */ public class test { public static void testPrintVoice(Animal c){ c.printVoice(); if(c instanceof Cat){ ((Cat)c).printRole(); } } public static void main(String[] args) { Animal a = new Cat(); Cat a2 = (Cat)a; //testPrintVoice(a); a.printVoice(); a2.printRole(); } }
运行结果:
喵喵
捉老鼠
内存分析:
注意:这次主要是分析多态,类的实例到方法区的指向在类的继承中给出分析,此处没做分析
分析:test类中主函数开始执行,依次加载test类Animal类和Cat类
3.2多态内存分析this 和super关键字
package 多态内存分析图代码2; /** * @author zhao xuke * * 2018年4月13日 - 下午6:35:29 */ public class Earth { public void toChina(){ System.out.println("Earth.toChina()"); toAmerica(); } public void toAmerica(){ System.out.println("Earth.toAmerica()"); } } class Word extends Earth{ public void toAmerica(){ System.out.println("Word.toAmerica()"); } }
package 多态内存分析图代码2; /** * @author zhao xuke * * 2018年4月13日 - 下午6:43:56 */ public class Test { public static void main(String[] args) { Earth e = new Word(); e.toChina(); } }
运行结果:
Earth.toChina()
Word.toAmerica()
内存分析图;