java基础——day08-2 接口、多态
接口
使用接口的注意事项
1、接口中是没有静态代码块和构造方法的
package day09.day08_1; public interface Myinterface { //错误写法 static { } //错误写法 public Myinterface(){ } }
2、一个类只能有一个父类,但是一个类可以实现多个接口
格式:
public class 类名 implements 接口1,接口2{//覆盖重写所有抽象方法}
package day09.day08_1; public interface MyinterfaceA { //定义抽象方法 public abstract void methodA(); }
package day09.day08_1; public interface MyinterfaceB { //定义抽象方法 public abstract void methodB(); }
package day09.day08_1; //实现A B接口 public class MyinterfaceImpl implements MyinterfaceA,MyinterfaceB { //实现类要实现多个接口中的抽象方法 @Override public void methodA() { System.out.println("come from interface A"); } @Override public void methodB() { System.out.println("come from interface B"); } }
package day09.day08_1; public class demo { public static void main(String[] args) { //定义实现类的对象 MyinterfaceImpl duixiang = new MyinterfaceImpl(); duixiang.methodA(); duixiang.methodB(); } }
3、若实现类所实现的多个接口中,存在重复抽象类,那么只需要覆盖重写一次即可
package day09.day08_1; public interface MyinterfaceA { //定义抽象方法 public abstract void methodA(); public abstract void methodC(); }
package day09.day08_1; public interface MyinterfaceB { //定义抽象方法 public abstract void methodB(); public abstract void methodC(); }
package day09.day08_1; //实现A B接口 public class MyinterfaceImpl implements MyinterfaceA,MyinterfaceB { //实现类要实现多个接口中的抽象方法 @Override public void methodA() { System.out.println("come from interface A"); } @Override public void methodB() { System.out.println("come from interface B"); } //A B中重复的抽象方法 实现类只需覆盖重写一次即可 @Override public void methodC() { System.out.println("I'm live in interface-A & B"); } }
package day09.day08_1; public class demo { public static void main(String[] args) { //定义实现类的对象 MyinterfaceImpl duixiang = new MyinterfaceImpl(); duixiang.methodA(); duixiang.methodB(); duixiang.methodC(); } }
4、若实现类没有覆盖重写接口的所有抽象方法,那么实现类要是抽象类
5、如果实现类实现的接口中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。
package day09.day08_1; public interface MyinterfaceA { //定义默认方法 public default void method(){ System.out.println("AAA"); } }
package day09.day08_1; public interface MyinterfaceB { //定义默认方法 public default void method(){ System.out.println("BBB"); } }
package day09.day08_1; //实现A B接口 public class MyinterfaceImpl implements MyinterfaceA,MyinterfaceB { //此时一定要对接口中的默认方法进行覆盖重写 @Override public void method() { System.out.println("CCC"); } }
package day09.day08_1; public class demo { public static void main(String[] args) { //定义实现类的对象 MyinterfaceImpl duixiang = new MyinterfaceImpl(); duixiang.method(); } }
6、一个类,如果父类中的方法和接口中的默认方法产生冲突,此时优先使用父类中的方法(继承 > 接口实现)
package day09.day08_1.day08_2; public class Test { public void method(){ System.out.println("this is father's method"); } }
package day09.day08_1.day08_2; public interface Myinterface { //定义默认方法 public default void method(){ System.out.println("this is interface default method"); } }
package day09.day08_1.day08_2; public class Myimplements extends Test implements Myinterface { }
package day09.day08_1.day08_2; public class demo { public static void main(String[] args) { Myimplements duixiang = new Myimplements(); duixiang.method(); //优先输出父类的方法 } }
多态
概述
多态是继封装、继承后,面向对象的第三大特征。
多态的现实体现:比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也
是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。

定义
多态:是指同一行为,具有多个不同表现形式。
前提【重点】:
1.继承或者实现【二选一】
2.方法的重写【意义体现:不重写,无意义】
3.父类引用指向子类对象【格式体现】
多态的体现
1.格式
父类名称 对象名 = new 子类名称();
接口名称 对象名 = new 实现类名称();
package day09.day08_1.day09_1; public class Fu { public void method(){ System.out.println("父类方法"); } public void methodFu(){ System.out.println("父类特有的方法"); } }
package day09.day08_1.day09_1; //子类 继承父类 public class Zi extends Fu { @Override public void method() { System.out.println("子类重写父类的方法"); } }
package day09.day08_1.day09_1; public class demo { public static void main(String[] args) { //使用多态的写法 创建子类 Fu obj = new Zi(); obj.method();//因为子类有 输出子类的方法 obj.methodFu(); //因为子类没有 调用父类的 //此时 子类就是一个父类 } }
注意:使用多态,代表子类就是一个父类 例如 学生 就是 一个人类的关系。
2.关于多态中的成员变量
访问成员变量的两种形式:
1.直接通过对象名访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
2.间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。
3.编译看左边,运行还看左边
package day09.day08_1.day09_2; public class Fu { int num = 10; public void showNum() { System.out.println(num); } }
package day09.day08_1.day09_2; public class Zi extends Fu { int num = 20; //测试访问成员变量会不会向下找 int age = 16; //覆盖重写了 @Override public void showNum() { System.out.println(age); } }
package day09.day08_1.day09_2; public class demo { public static void main(String[] args) { //使用多态的写法 Fu obj = new Zi(); //直接方法 System.out.println(obj.num);//发现其会指向父类 // System.out.println(obj.age); 错误写法! System.out.println("=================="); obj.showNum(); //若子类没有覆盖重写——父:10 若重写了 就是——子16 } }
3.多态中的成员方法
多态代码中成员方法访问规则:
1、看new的左边是谁,就优先找谁,没有则向上找。
2、编译看左边,运行看右边
package day09.day08_1.day09_3; public class Fu { public void method(){ System.out.println("父类方法"); } public void methodA(){ System.out.println("父类特有方法"); } }
package day09.day08_1.day09_3; public class Zi extends Fu { public void method(){ System.out.println("子类方法"); } public void methodB(){ System.out.println("子类特有方法"); } }
package day09.day08_1.day09_3; public class demo { public static void main(String[] args) { //使用多态形式 Fu obj = new Zi(); obj.method(); //父子都有 优先用子 obj.methodA(); //父类特有 //编译看左边:左边是Fu,Fu当中没有methodB方法,所以编译报错 //obj.methodB(); //错误写法 } }
多态的好处
实际开发中,父类类型作为方法形式参数(形参),传递子类对象给方法,进行方法的调用,更能体现多态的扩展性与便利。

例如:对比 多态类定义的对象调用方法 和 普通定义的对象调用方法
package day09.day08_1.day09_4; //定义一个抽象父类——动物类 public abstract class Animal { //定义动物类 eat()抽象方法 public abstract void eat(); }
package day09.day08_1.day09_4; //定义子类——猫类 继承动物类 public class Cat extends Animal{ @Override public void eat() { System.out.println("吃鱼"); } }
package day09.day08_1.day09_4; //定义子类——狗类 继承动物类 public class Dog extends Animal { @Override public void eat() { System.out.println("吃骨头"); } }
package day09.day08_1.day09_4; public class demo { public static void main(String[] args) { //使用多态方式定义 Cat Dog对象 Animal cat = new Cat(); Animal dog = new Dog(); cat.eat(); dog.eat(); System.out.println("=======对比========="); //使用普通方式定义Cat Dog对象 Cat cat1 = new Cat(); Dog dog1 = new Dog(); //调用showCatEat showCatEat(cat1); //调用showDogEat showDogEat(dog1); } public static void showCatEat(Cat cat){ cat.eat(); } public static void showDogEat(Dog dog){ dog.eat(); } }
多态的好处,可以使程序编写的更加简单,并具有良好的扩展性。
引用类型转换
多态转型分为两种:向上转型 向下转型
向上转型
向上转型:多态本身是 子类类型 向 父类类型向上转换的过程,这个过程也是默认的。
当父类引用 指向 子类对象时,便是向上转型。(小范围 转型 大范围)
类似 int 转型为 double
使用格式:
父类类型 变量名 = new 子类类型();
Animal cat = new Cat();
向上转型一定是安全的,没问题的,正确的,但是存在其弊端
弊端:对象一旦向上转型为父类,那么对象无法调用子类原本特有的方法
解决方案:用对象的向下转型【还原】
向下转型
向下转型:父类类型 向 子类类型 向下转型的过程,是强制的。
含义:将父类对象,【还原】成为本来的子类对象。
使用格式:
子类类型 变量名 = (子类类型) 父类对象;
Animal cat = new Cat(); //本来是猫 向上转型为 动物
Cat cat = (Cat) animal; //本来是猫 还原 为猫 (向下转型)
注意事项:
1.必须保证对象本来创建的时候,就是子类1的对象,才能向下转型为原来的子类1对象
2.如果对象创建的时候,不是子类1的对象,现在非要转型为子类1的对象,就会报错。(只有创建时为同类型的 才能向下转型)
其含义可以理解为:
int num = (int)10.0 //可以
int num = (int)10.5 //不可以 精度损失
例如:
package day09.day08_1.day09_4; //定义一个抽象父类——动物类 public abstract class Animal { //定义动物类 eat()抽象方法 public abstract void eat(); }
package day09.day08_1.day09_4; //定义子类——猫类 继承动物类 public class Cat extends Animal{ @Override public void eat() { System.out.println("吃鱼"); } //定义特有方法 抓老鼠 public void catchMoise(){ System.out.println("抓老鼠"); } }
package day09.day08_1.day09_4; //定义子类——狗类 继承动物类 public class Dog extends Animal { @Override public void eat() { System.out.println("吃骨头"); } }
package day09.day08_1.day09_4; public class demo { public static void main(String[] args) { //使用多态方式定义 Cat Dog对象 Animal animal = new Cat(); //本来创建的时候是一只猫 Animal dog = new Dog(); animal.eat(); //正确 // animal.catchMoise(); 错误! 多态创建的对象 不能访问自己独有的方法 //向下转型 进行还原 Cat cat1 = (Cat)animal; cat1.catchMoise(); } }
判断对象本来是什么子类——Instanceof
1.问题:如何知道一个父类引用的对象,本来是什么子类?
2.解决:使用Instanceof关键字,给引用变量做类型校验
3.格式:对象 instanceof 数据类型 //会得到一个boolean结果
package day09.day08_1.day09_4; //定义一个抽象父类——动物类 public abstract class Animal { //定义动物类 eat()抽象方法 public abstract void eat(); }
package day09.day08_1.day09_4; //定义子类——猫类 继承动物类 public class Cat extends Animal{ @Override public void eat() { System.out.println("吃鱼"); } //定义特有方法 抓老鼠 public void catchMoise(){ System.out.println("抓老鼠"); } }
package day09.day08_1.day09_4; //定义子类——狗类 继承动物类 public class Dog extends Animal { @Override public void eat() { System.out.println("吃骨头"); } public void seeHouse(){ System.out.println("看家"); } }
package day09.day08_1.day09_4; public class demoInstenceof { //如何知道一个父类引用的对象,本来是什么子类 // public static void main(String[] args) { Animal animal = new Dog(); //买了狗 giveMePet(animal); } //当女朋友说随便买宠物 判断女朋友到底想要什么宠物 public static void giveMePet(Animal animal){ //如果是狗 尽其职 看家 if(animal instanceof Dog){ Dog dog = (Dog) animal; dog.seeHouse(); } //如果是猫 尽其职 抓老鼠 if(animal instanceof Cat){ Cat cat = (Cat)animal; cat.catchMoise(); } } }
Tip:通过判断后,使用向下转型更安全
练习:接口多态的综合案例
question:笔记本电脑(laptop)通常具备使用USB设备的功能。在生产时,笔记本都预留了可以插入USB设备的USB接口,但具体是什么USB设备,笔记本厂商并不关心,只要符合USB规格的设备都可以。
定义USB接口,具备最基本的开启功能和关闭功能。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守USB规范,实现USB接口,否则鼠标和键盘的生产出来也无法使用。
分析:
1.usb接口,包含打开和关闭功能
2.笔记本类,包含运行、关机、使用USB设备功能
3.鼠标类,要实现USB接口,并具备点击方法
4.键盘类,要实现USB接口,并具备敲击的方法
package day09.day08_1.day09_5; public interface USB { public abstract void open(); public abstract void close(); }
package day09.day08_1.day09_5; public class Mouse implements USB { @Override public void open() { System.out.println("鼠标开启,红灯闪一闪"); } @Override public void close() { System.out.println("鼠标关闭,红灯熄灭"); } //定义点击方法 public void click(){ System.out.println("鼠标单击"); } }
package day09.day08_1.day09_5; public class keyBoard implements USB { @Override public void open() { System.out.println("键盘开启,绿灯闪一闪"); } @Override public void close() { System.out.println("键盘关闭,绿灯熄灭"); } //定义敲击方法 public void hit(){ System.out.println("键盘敲击"); } }
package day09.day08_1.day09_5; import javax.swing.*; public class Computer { //电脑开机运行功能 public void run(){ System.out.println("电脑已开始运行"); } //定义电脑关机 public void shutdown(){ System.out.println("电脑关机"); } public void useUsb(USB usb){ if(usb != null){ usb.open(); //类型转换,调用特有方法 if(usb instanceof Mouse){ Mouse mouse = (Mouse) usb; mouse.click(); } if(usb instanceof keyBoard){ keyBoard kb = (keyBoard)usb; kb.hit(); } usb.close(); } } }
package day09.day08_1.day09_5; import javax.swing.*; public class demo { public static void main(String[] args) { Computer computer = new Computer(); //开启电脑 computer.run(); //创建鼠标实体对象 Mouse mouse = new Mouse(); //接入鼠标并点击 computer.useUsb(mouse); //创建键盘实体对象 keyBoard jp = new keyBoard(); //接入键盘并敲击 computer.useUsb(jp); //关机 computer.shutdown(); } }

浙公网安备 33010602011771号