面向对象(多态)
一、方法覆盖
方法重载:同一个类,两个或者两个以上,方法名称一致,参数列表不一致,跟其他无关(static,void,public)
方法覆盖(重写):子类继承并且改变了方法体,其他不能改变(访问修饰符,异常)
-
static方法不能覆盖和重写,因为静态的方法是跟类绑定,子类写了和父类一样的静态方法,并不是覆盖
static是模板,只能继承,不能覆盖
package com.szwollf.Day08.DemoOverride; public class Person { private String name; private String sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } //说话 public void speak(){ System.out.println("人说人话!"); } //静态方法 public static void fun(){ System.out.println("我是父类的静态方法!!!!"); } } package com.szwollf.Day08.DemoOverride; public class AmericaPerson extends Person{ // @Override//可以不标明覆盖 但是最好标明 public void speak(){ System.out.println("Hello! nice to meet you!"); } } package com.szwollf.Day08.DemoOverride; public class ChinesePerson extends Person{ //说话-- 中国人 // public void speak(){//这里不写则不覆盖 直接使用父类的方法 // System.out.println("华为牛逼"); // } //静态方法 public static void fun(){ System.out.println("我是子类的静态方法!!!!"); } } package com.szwollf.Day08.DemoOverride; public class Test { public static void main(String[] args) { ChinesePerson cp=new ChinesePerson(); cp.speak(); AmericaPerson ap=new AmericaPerson(); ap.speak(); } }
二、多态
三大特征:封装 继承 多态
同一个动作,在不同地方,表现的形态是不同的(龙生九子,各有不同)
多态的前提条件:
-
继承(每个子都从龙父那里继承了一些变量和方法)
-
重写覆盖(同时由产生变异,每个实例由改写了方法体)
-
子类类型向上转型(可以向上和向下转换,变量不能向上转型所以不能多态)
多态能调用的方法,都是父子共有的方法,执行的是子类的方法
package com.szwollf.Day08.DemoPolymorphic; public class Animal { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } //方法 movie() 动 public void movie(){ System.out.println("动物动"); } } package com.szwollf.Day08.DemoPolymorphic; public class Cat extends Animal{ @Override public void movie() { System.out.println("猫爬"); } public void catchMouse(){ System.out.println("只有猫会捉老鼠!"); } } package com.szwollf.Day08.DemoPolymorphic; public class Dog extends Animal{ @Override public void movie() { System.out.println("狗跑"); } } package com.szwollf.Day08.DemoPolymorphic; public class Test { public static void main(String[] args) { Cat c1 = new Cat(); c1.setName("狸猫-小黑"); System.out.println(c1.getName()); c1.movie(); c1.catchMouse();//猫类独有的必须是向下转型的才能使用 Dog d1 = new Dog(); d1.setName("旺财"); System.out.println(d1.getName()); d1.movie(); //Animal 是 父类 Cat是子类---向上转型 Animal c2=new Cat(); c2.setName("小黑"); System.out.println(c2.getName()); c2.movie(); //c2.catchMouse();//不能调用 Animal d2=new Dog();//向上转型 d2.setName("旺财"); System.out.println(d2.getName()); d2.movie(); } }
因为多态能调用的方法是父子共有的,子类独有的方法多态是不能调用的,怎么办呢?使用向下转型
向下转型引发的问题:
java.lang.ClassCastException 类型转换异常
Animal cat=new Cat(); Dog cat1 = (Dog) cat;//向上才可以强转
new 的是谁,转换成谁,不要犯错
转换为了防止出现转换异常,用 instanceof 关键字来进行判断
变量 instanceof 类型 ----运算符
判断 前边变量 属于不属于 后面的类型? 结果是boolean类型
cat instanceof Cat 判断变量 cat 属于Cat类型吗?
if(cat instanceof Dog){//前面的是否属于后面的具象化 Dog cat1 = (Dog) cat; }else { System.out.println("cat不属于Dog类型,不能转换!"); }
以后再进行引用数据类型的转换都要先判断是不是要转换的类型,养成习惯!
-
子类独有的方法,为什么不直接new子类呢?而非要用多态,再向下转型呢?
后期,拿到对象是别人给的,别人给的形态就是父类类型,具体的代码通过使用多态的向下转型而来,即给出框架,我们用多态围绕框架编程
为什么别人不直接给我子类类型呢?而是给我一个父类类型?
多态的优点:耦合度降低,参数作为抽象的类,面向抽象编程
手机耦合度太高了----------内存不够用-------换手机
电脑-------------------4g不够-----8g---16g----------------耦合度低
代码的方向:高内聚,低耦合
讲课 ,一个老师一个阶段,耦合度不高
三、super关键字
super关键字指当前对象的父类对象的特征
this指当前对象
package com.szpowernode.day08.superdemo; //父类 public class Person { String name; } package com.szpowernode.day08.superdemo; //子类 public class Student extends Person { public void fun(){ System.out.println(this);//s1 System.out.println(this.name);// // System.out.println(super); //super不是一个对象,使用上跟this基本一样 System.out.println("super:"+super.name); } } package com.szpowernode.day08.superdemo; public class TestStudent { public static void main(String[] args) { Student s1=new Student(); s1.name="张三"; System.out.println("s1:"+s1.name); s1.fun(); } }
super 不是对象,因为不能直接输出,如果是对象就可以输出
-
super应用
this在构造函数使用 this(【参数列表】) 第一行
super([参数列表])第一行
package com.homework.Day07.Demo01; public class Monkey { private String name; private char gender; public void speak(String sentence){ System.out.println(sentence); } public Monkey() {} public Monkey(String name,char gender) { this.name = name; this.gender = gender; } public void setName(String name) { this.name = name; } public void setGender(char gender) { this.gender = gender; } public String getName() { return name; } public char getGender() { return gender; } } package com.homework.Day07.Demo01; public class Person extends Monkey{ public Person() {} public Person(String name,char gender) { super(name,gender);就是把子类构造函数的参数传给父类 }//子类构造函数调用前会先调用父类无参 } package com.szpowernode.day08.thisandsuper; public class TestZi { public static void main(String[] args) { Zi zi=new Zi("刘备","男","女"); System.out.println(zi.name); System.out.println(zi.sex); System.out.println(zi.hobby); } } package com.homework.Day07.Demo01; public class Test { public static void main(String[] args) { Person p=new Person(); p.speak("我是珍妮"); p.setGender('男'); p.setName("飞科"); System.out.println(p.getGender()); System.out.println(p.getName()); Person p2=new Person("哈哈",'女'); System.out.println(p2.getGender()); System.out.println(p2.getName()); } }
super()调用父类对象的构造函数 必须在第一行
-
super调用父类方法以及变量多态
package com.szwollf.Day08.DemoDragon; public class Dragon { String name="蛟龙"; public void Fire(){ System.out.println("喷火"); } } package com.szwollf.Day08.DemoDragon; public class TaoTie extends Dragon{ String name="饕餮"; @Override public void Fire(){ System.out.println("喷水"); super.Fire(); } } package com.szwollf.Day08.DemoDragon; public class Test { public static void main(String[] args) { TaoTie tt=new TaoTie(); tt.Fire(); Dragon tt2=new TaoTie(); tt2.Fire();//赋值给父类 变量名.成员方法 用的还是子类重写的方法 System.out.println(); Dragon dg=new TaoTie(); System.out.println(dg.name);//向上转型时 变量名.成员变量 用的是父类的成员变量 并没有覆盖 // dg.name="饕餮"; ((TaoTie)dg).name="饕餮";//把父类强转子类然后改值,父类没变 System.out.println(dg.name);//依旧是父类的蛟龙 System.out.println(((TaoTie)dg).name);//改的是这个 不是父类的name } }
多态
父类 变量 = new 子类();
变量.成员变量还是父类的
变量.成员方法是子类
总结:
子类继承并改写父类方法的方法体可以覆盖,而子类重写成员变量却不能覆盖
即new的子类对象方法赋值给父类类型的变量时,把父类本身的方法给重写了,即子类的方法有两种类型,一种子类类型,一种父类类型,这就是多态,所以多态的条件为继承(覆盖的前提),覆盖(如果不能覆盖那就是子类和父类是分开的并不是子类的多种形态),向上转型(即子类的方法可以是父类类型)
多态:子类的方法向上转为父类类型
变量那个并不是跨类覆盖,而是子类父类各写各的,你子类赋值给子类,子类把子类覆盖,那当然是子类的变量,你子类赋值给父类,还是父类,覆盖失败,父类强转子类在赋值变量,父类依旧没被覆盖。
对于成员变量来说不能多态,所以变量是什么类型就是什么类型
对于成员方法来说能多态,所以方法用哪个类型看new的是哪个,new父类用父类,new子类,子类覆盖父类。用子类方法。
java语言设计者,只是设计了方法的覆盖重写,没有设计成员变量的覆盖和重写
四、递归(Day04)
package com.szwollf.Day08; public class Recursion { public static void main(String[] args) { System.out.println(calc(10)); } public static int calc(int n){ n = n/2; System.out.println(n);//5 2 1 0压栈 if (n > 0) { calc(n);//调用自己 } return n;//0 1 2 5出栈 } }

如上图所示,函数在每进入下一层的时候,当前层的函数并未结束,它必须等它调用的下一层函数执行结束返回后才能继续往下走。 所以最下面的那句print(n)会等最里层的函数执行时才会执行,然后不断往外退层,所以会出现0、1、2、5的效果
递归特性:
-
必须有一个明确的结束条件
-
每次进入更深一层递归时,问题规模相比上次递归都应有所减少
-
递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
递归通常用于多级菜单

浙公网安备 33010602011771号