回顾与重点
模块十回顾
-
继承:子类继承父类,可以直接使用父类中非私有成员,子类不用写重复性代码
-
关键字:extends
-
成员访问特点:
a. 成员变量:看等号左边是谁
b. 成员方法:看new的是谁
-
方法的重写:子类中有一个和父类从方法名以及参数列表上一样的方法
a. 检测:@Override
b. 使用场景:功能升级
-
继承中的构造的特点:
new子类对象先初始化父类
-
super:代表的是父类引用
a. 调用父类构造:super() super(实参)
b. 调用父类成员变量:super.成员变量
c. 调用父类成员方法:super.成员方法名(实参)
-
this:代表的是当前对象(哪个对象调用的this所在的方法,this就代表哪个对象)
a. 作用:区分重名的成员变量和局部变量
b. 作用:
调用当前对象构造:this() this(实参)
调用当前对象成员变量:this.成员变量名
调用当前成员方法:this.成员方法名(实参)
c. 注意:在构造中使用this和super,都必须要在第一行,所以两者不能同时出现
-
继承的特点:
a. 继承只支持单继承,不支持多继承
b. 继承支持多层继承
c. 一个父类可以拥有多个子类
-
抽象
a. 抽象方法
修饰符 abstract 返回值类型 方法名(形参)
b. 抽象类
public abstract class 类名{}
c. 特点
抽象方法所在的类一定是抽象类
抽象类中不一定非得有抽象方法
子类继承抽象父类时,需要重写抽象方法
抽象类不能new对象,只能new子类对象
抽象类中啥都可以有,私有属性、构造方法、其他方法等
抽象类中的构造时供创建子类对象时初始化父类属性使用的
模块十一重点
- 会定义接口
- 会在接口中定义抽象方法,默认方法,静态方法、成员变量
- 会调用接口中的成员
- 知道多态的前提
- 会利用多态的方式new对象
- 要知道使用多态的好处
- 会在多态的前提下向下转型
- 会使用instanceof类型判断
第一章 接口
1.1 接口的介绍
-
接口:是一个引用数据类型,是一种标准,规则
-
关键字:
a. interface 接口
public interface 接口名{}
b. implements 实现
实现类 implements 接口名{}
-
接口中可以定义的成员:
a. jdk7以及之前
抽象方法:public abstract → 即使不写public abstract,默认也有
成员变量:public static final 数据类型 变量名 = 值 → 即使不写public static final ,默认也有
final是最终的,被final修饰的变量不能二次赋值,所以我们一般将final修饰的变量视为常量
b. jdk8:
默认方法:public default 返回值类型 方法名(形参) {}
静态方法:public static 返回值类型 方法名(形参) {}
c. jdk9开始:
私有方法:private的方法
1.2 接口的定义以及使用
-
定义接口
public interface 接口名{}
-
实现
public class 实现类名 implements 接口名 {}
-
使用
a. 实现类实现接口
b. 重写接口中的抽象方法
c. 创建实现类对象(接口不能直接new对象)
d. 调用重写的方法
public interface USB {public abstract void open();public abstract void close();
}
public class Mouse implements USB {@Overridepublic void open() {System.out.println("鼠标打开");}@Overridepublic void close() {System.out.println("鼠标关闭");}
}
public class Test01 {public static void main(String[] args) {Mouse mouse = new Mouse();mouse.open();mouse.close();}
}
1.3 接口中的成员
1.3.1 抽象方法
-
定义格式
public abstract 返回值类型 方法名(形参)
-
注意:
不写public abstract 默认也有
-
使用
a. 定义实现类,实现接口
b. 重写抽象方法
c. 创建实现类对象,调用重写的方法
public interface USB {public abstract void open();String close();
}
public class Mouse implements USB{@Overridepublic void open() {System.out.println("鼠标打开");}@Overridepublic String close() {return "鼠标关闭";}
}
public class Test01 {public static void main(String[] args) {Mouse mouse = new Mouse();mouse.open();String str = mouse.close();System.out.println("str = " + str);}
}
1.3.2 默认方法
-
定义格式
public default 返回值类型 方法名(形参) {方法体return 结果 }
-
使用
a. 定义实现类,实现接口
b. 默认方法可重写,可不重写
c. 创建实现类对象,调用默认方法
public interface USB {// 默认方法public default void methodDef() {System.out.println("我是默认方法");}
}
public class Mouse implements USB {@Overridepublic void methodDef() {System.out.println("我是重写接口中的默认方法");}
}
public class Test01 {public static void main(String[] args) {Mouse mouse = new Mouse();mouse.methodDef();}
}
1.3.3 静态方法
-
定义格式
public static 返回值类型 方法名(形参) {方法体return 结果 }
-
使用
接口名直接调用
public interface USB {// 默认方法public default void methodDef() {System.out.println("我是默认方法");}// 静态方法public static void methodSta() {System.out.println("我是接口中的静态方法");}
}
public class Test01 {public static void main(String[] args) {Mouse mouse = new Mouse();mouse.methodDef();System.out.println("==================================");// 静态方法 接口名直接调用USB.methodSta();}
}
默认方法和静态方法 → 可以作为临时加的一个小功能来使用,直接修改接口对应的实现类都会报错。
1.3.4 成员变量
-
格式
public static final 数据类型 变量名 = 值
-
相关知识点:final
final代表最终的,被它修饰的变量,不能二次赋值,可以视为常量
-
特点:
不写public static final 默认也有
-
使用
接口名直接调用
-
注意
a. 被static final 修饰的成员变量需要手动赋值
b. 习惯上我们会将static final修饰的成员变量名大写
public interface USB {// 成员变量public static final int NUM1 = 100;int NUM2 = 200; // 不写 public static final 默认也有
}
public class Test01 {public static void main(String[] args) {System.out.println(USB.NUM1);System.out.println(USB.NUM2);}
}
1.4 接口的特点
-
接口可以多继承 → 一个接口可以继承多个接口
public interface InterfaceA extends InterfaceB,InterfaceC {}
-
接口可以多实现 → 一个实现类可以实现一个或者多个接口
public class InterfaceImp1 implements InterfaceA,InterfaceB {}
-
一个子类可以继承一个父类的同时实现一个或者多个接口
public class Zi extends Fu implements InterfaceA,InterfaceB {}
-
注意
继承也好,实现接口也罢,只要是父类中或者接口的抽象方法,子类或者实现类都要重写
当一个类实现多个接口时,如果接口中的抽象方法有重名且参数一样的,只需要重写一次。
// InterfaceA接口 public interface InterfaceA {public abstract void method(); }// InterfaceB接口 public interface InterfaceB {public abstract void method(); }// InterfaceImpl 实现类 public class InterfaceImpl implements InterfaceB,InterfaceA {@Overridepublic void method() {System.out.println("重写的method方法");} }
当一个类实现多个接口时,如果多个接口中默认方法有重名的且参数一样的,必须重写一次默认方法
public interface InterfaceA {public abstract void method();public default void methodDef() {System.out.println("我是接口A中的默认方法");} }public interface InterfaceB {public abstract void method();/*public default void methodDef() {System.out.println("我是接口B中的默认方法");}*/public default void methodDef(int b) {System.out.println("我是接口B中的默认方法");} }public class InterfaceImpl implements InterfaceB,InterfaceA {@Overridepublic void method() {System.out.println("重写的method方法");}/*@Overridepublic void methodDef() {System.out.println("重写后的默认方法");}*/ }public class Test01 {public static void main(String[] args) {InterfaceImpl anInterface = new InterfaceImpl();anInterface.method();anInterface.methodDef();anInterface.methodDef(10);} }
1.5 接口和抽象类的区别
相同点:
a. 都位于继承体系的顶端,用于被其他类实现或者继承
b. 都不能new
c. 都包含抽象方法,其子类或者实现类都必须重写这些抽象方法
不同点:
a. 抽象类:一般作为父类使用,可以有成员变量、构造方法、成员方法、抽象方法等
b. 接口:成员单一,一般抽取接口,抽取的都是方法,视为功能的大集合
c. 类不能多继承,但是接口可以
第二章 多态
-
面向对象三大特征:封装、继承、多态
-
怎么学:
a. 不要从字面意思上理解多态这两个字,要从使用形式上掌握
b. 要知道多态的好处
c. 要知道多态的前提
2.1 多态的介绍
-
前提:
a. 必须有子父类继承或者接口实现关系
b. 必须要有方法的重写(没有重写,多态没有意义),多态玩的主要是重写方法
c. new对象:父类引用指向子类对象
Fu fu = new Zi() → 理解为大类型接收一个小类型的数据 → 比如 double b = 10
-
注意:
a. 多态下不能直接调用子类特有功能
2.2 多态的基本使用
public abstract class Animal {public abstract void eat();
}
public class Dog extends Animal{@Overridepublic void eat() {System.out.println("狗啃骨头");}// 特有方法public void lookDoor() {System.out.println("狗会看门");}
}
public class Cat extends Animal{@Overridepublic void eat() {System.out.println("猫吃鱼");}// 特有方法public void catchMouse() {System.out.println("猫会捉老鼠");}
}
public class Test01 {public static void main(String[] args) {// 原始方式Dog dog = new Dog();dog.eat(); // 重写的dog.lookDoor(); // 特有的Cat cat = new Cat();cat.eat(); // 重写的cat.catchMouse(); // 特有的System.out.println("====================");// 多态形式new对象Animal animal = new Dog(); // 相当于 double b = 10animal.eat(); // 重写的 animal 接收的是dog对象,所以调用的是dog中的eat// animal.lookDoor(); // 多态前提下,不能直接调用子类特有对象Animal animal1 = new Cat();animal1.eat(); // cat 重写的}
}
2.3 多态条件下成员的访问特点
2.3.1 成员变量
public class Fu {int num = 1000;
}
public class Zi extends Fu {int num = 100;
}
public class Test01 {public static void main(String[] args) {Fu fu = new Zi();System.out.println(fu.num); // 1000}
}
成员变量,看等号左边是谁,先调用谁中的变量。
2.3.2 成员方法
public class Fu {int num = 1000;public void method() {System.out.println("我是父类中的method");}
}
public class Zi extends Fu {int num = 100;public void method() {System.out.println("我是子类中的method");}
}
public class Test01 {public static void main(String[] args) {Fu fu = new Zi();System.out.println(fu.num); // 1000fu.method(); // 子类中重写的method方法}
}
成员方法,看new的是谁,先调用谁中的成员方法,子类没有找父类。
2.4 多态的好处(为什么要学多态)
-
问题描述
如果使用原始方式new对象(等号左右两边一样),既能调用重写的,还能调用继承的,还能调用自己特有的成员
但是多态方式new对象,只能调用重写的,不能直接调用子类特有的成员,那为什么还要用多态呢?
-
多态方式和原始方式new对象的优缺点:
原始方式:
a. 优点:既能调用重写的,还能调用父类非私有的,还能调用自己特有的
b. 缺点:扩展性差
多态方式:
a. 优点:扩展性强
b. 缺点:不能直接调用子类特有功能
public abstract class Animal {public abstract void eat();
}
public class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼");}// 特有方法public void catchMouse() {System.out.println("猫会捉老鼠");}
}
public class Dog extends Animal {@Overridepublic void eat() {System.out.println("狗啃骨头");}// 特有方法public void lookDoor() {System.out.println("狗会看门");}
}
public class Test01 {public static void main(String[] args) {// 原始方式Dog dog = new Dog();method(dog);Cat cat = new Cat();method(cat);/*如果还有其他得动物子类,还需要重新定义method方法,重新指定相应得子类对象,扩展性极差*/}public static void method(Dog dog) {dog.eat();}public static void method(Cat cat) {cat.eat();}
}
public class Test02 {public static void main(String[] args) {// 多态方式Animal animal = new Dog();animal.eat();animal = new Cat();animal.eat();System.out.println("=====================");Dog dog = new Dog();method(dog); // 传递参数 Animal animal = new Dog();Cat cat = new Cat();method(cat); // 传递参数 Animal animal = new Cat();}/*形参传递父类类型,调用此方法父类类型可以接收任意它的子类对象传递哪个子类对象,就指向哪个子类对象,就调用哪个子类对象重写的方法*/public static void method(Animal animal) {animal.eat();}
}
形参传递父类类型,调用此方法父类类型可以接收任意它的子类对象,传递哪个子类对象,就指向哪个子类对象,就调用哪个子类对象重写的方法。
2.5 多态中的转型
2.5.1 向上转型
-
向上转型:父类引用指向子类对象
比如:double b = 1;
-
表现方式
父类类型 对象名 = new 子类对象() → 向上转型 → double b = 1
2.5.2 向下转型
-
向下转型:好比强转,将大类型强制转成小类型
-
表现方式
子类类型 对象名 = new 子类对象() → 向上转型 → double b = 1 子类类型 对象名1 = (子类类型) 对象名 → 向下转型 int i = (int)b
-
想要调用子类特有功能,我们就需要向下转型
public abstract class Animal {public abstract void eat();
}
public class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼");}// 特有方法public void catchMouse() {System.out.println("猫会捉老鼠");}
}
public class Dog extends Animal {@Overridepublic void eat() {System.out.println("狗啃骨头");}// 特有方法public void lookDoor() {System.out.println("狗会看门");}
}
public class Test01 {public static void main(String[] args) {// 多态方式 向上转型Animal animal = new Dog();animal.eat(); // dog 重写的// animal.lookDoor(); // 多态下不能调用子类特有功能// 向下转型Dog dog = (Dog) animal;dog.eat();dog.lookDoor();}
}
2.6 转型可能会出现的问题
-
如果等号两边类型不一致,会出现类型转换异常(ClassCastException)
-
解决
在向下转型之前,先判断类型
-
怎么判断类型:instanceof
判断结果是boolean型
-
使用
对象名 instanceof 类型 → 判断的是关键字前面的对象是否符合=关键字后面的类型
public abstract class Animal {public abstract void eat();
}
public class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼");}// 特有方法public void catchMouse() {System.out.println("猫会捉老鼠");}
}
public class Dog extends Animal {@Overridepublic void eat() {System.out.println("狗啃骨头");}// 特有方法public void lookDoor() {System.out.println("狗会看门");}
}
public class Test01 {public static void main(String[] args) {Dog dog = new Dog();method(dog);System.out.println("==================");Cat cat = new Cat();method(cat);}public static void method(Animal animal) {/*animal.eat();*//*这里会出现类型转换异常(ClassCastException)原因:当调用method,传递Cat对象时,animal代表的就是Cat对象,此时我们将代表cat对象的animal强转成了dog此时等号左右两边类型不一致了,所以出现类型转换异常*//*Dog dog = (Dog) animal;dog.lookDoor();*/if (animal instanceof Dog) {Dog dog = (Dog) animal;dog.eat();dog.lookDoor();}if (animal instanceof Cat) {Cat cat = (Cat) animal;cat.eat();cat.catchMouse();}}
}
2.7 综合练习
定义笔记本类,具备开机,关机和使用USB设备的功能。具体是什么USB设备,笔记本并不关心,只要符合USB规格的设备都可以。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守USB规范,不然鼠标和键盘的生产出来无法使用;
进行描述笔记本类,实现笔记本使用USB鼠标,USB键盘
- USB接口,包含开启功能、关闭功能
- 笔记本类,包含运行功能、关机功能、使用USB设备功能
- 鼠标类,要符合USB接口
- 键盘类,要符合USB接口
public interface USB {public abstract void open();public abstract void close();
}
public class Mouse implements USB{@Overridepublic void open() {System.out.println("鼠标开启");}@Overridepublic void close() {System.out.println("鼠标关闭");}// 特有方法public void click() {System.out.println("点击鼠标");}
}
public class Keyboard implements USB{@Overridepublic void open() {System.out.println("键盘开启");}@Overridepublic void close() {System.out.println("键盘关闭");}// 特有方法public void strikeKeyboard() {System.out.println("敲击键盘");}
}
public class NoteBookComputer {public void start() {System.out.println("开机");}public void useUSB(USB usb) {if (usb instanceof Mouse) {Mouse mouse = (Mouse) usb;mouse.open();mouse.click();mouse.close();} else if (usb instanceof Keyboard){Keyboard keyboard = (Keyboard) usb;keyboard.open();keyboard.strikeKeyboard();keyboard.close();}}public void close() {System.out.println("关机");}
}
public class Test01 {public static void main(String[] args) {NoteBookComputer noteBookComputer = new NoteBookComputer();Mouse mouse = new Mouse();noteBookComputer.start();noteBookComputer.useUSB(mouse);noteBookComputer.close();System.out.println("================");Keyboard keyboard = new Keyboard();noteBookComputer.start();noteBookComputer.useUSB(keyboard);noteBookComputer.close();}
}