day10【接口、多态】
一. 接口
1. 接口的创建和实现格式
(1) 如何创建接口
public interface 接口名 {
}
(2) 如何实现接口
public class 类 implements 接口名 {
}
接口的多实现
public class 类 implements 接口1, 接口2, 接口3 {
}
2. 接口中成员的定义格式(特点)
(1) 抽象方法
// public abstract : 可以省略, 默认存在
public abstract 返回值类型 方法名(参数列表);
(2) 默认方法(jdk1.8)
// public : 可以省略, 默认存在
public default 返回值类型 方法名(参数列表) {
}
(3) 静态方法(jdk1.8)
// public : 可以省略, 默认存在
public static 返回值类型 方法名(参数列表) {
}
(4) 私有方法(jdk9)
// 私有普通方法
private 返回值类型 方法名(参数列表) {
}
// 私有静态方法
private static 返回值类型 方法名(参数列表) {
}
(5) 自定义常量
// public static final : 可以省略, 默认存在
public static final 数据类型 常量名 = 值;
3. 接口中成员的使用(了解)
- 抽象方法: 用来让子类重写
- 默认方法: 用来让子类继承, 继承之后可以直接使用, 子类也可以重写默认方法
- 静态方法: 用来直接使用
接口名.静态方法
, 不能使用子类对象去调用 - 私有方法: 用来为本接口中的默认方法和静态方法服务
4. 接口和抽象类的特点
抽象类 | 接口 | |
---|---|---|
创建对象 | 不能创建对象 | 不能创建对象 |
构造方法 | 有构造方法, 给子类初始化 | 没有构造方法 |
抽象方法 | 子类必须重写 | 子类必须重写 |
普通方法 | 可以有普通方法 | 只能有抽象,默认,静态私有方法 |
5. 接口中方法同名的注意事项
- 场景: 类在继承父类的同时, 再实现多个接口
public class Zi extends Fu implements Inter1, Inter2 {
}
出现的注意事项
- 两个接口中有同名的抽象方法, 只需要重写一次.
- 两个接口中有同名的默认方法, 必须重写默认方法.
- 父类中的方法和接口中的默认方法同名.
6. 接口的多继承
public interface Inter2 extends Inter3, Inter4{
}
组合 | 关系 |
---|---|
类与类 | 继承, 只支持单继承, 不支持多继承, 但是支持多层继承 |
类与接口 | 实现, 可以多实现 |
接口与接口 | 继承, 可以多继承 |
二. 多态
1. 多态的前提
- 多态: 同一种事物的多种形态.
多态的前提
- 要有继承/实现关系
- 要有方法的重写(没有重写多态则没有意义)
- 要有父类引用指向子类对象(Fu fu = new Zi()?
多态中成员的使用特点
- 成员变量
- 编译看父类(左边), 运行也看父类(左边)
- 成员方法
- 编译看父类(左边), 运行看子类(右边)
2. 多态的好处(重点)
- 多态主要应用在方法的参数传递.
代码
- 父类
public abstract class Fu {
public abstract void fun();
}
- 子类
public class Zi1 extends Fu {
@Override
public void fun() {
System.out.println("Zi111重写的方法");
}
}
// ===================================================
public class Zi2 extends Fu {
@Override
public void fun() {
System.out.println("Zi222重写的方法");
}
}
// ===================================================
public class Zi3 extends Fu {
@Override
public void fun() {
System.out.println("Zi333重写的方法");
}
}
- 测试类
public class Demo03_多态的好处1 {
public static void main(String[] args) {
Zi1 zi1 = new Zi1();
fun(zi1);
Zi2 zi2 = new Zi2();
fun(zi2);
Zi3 zi3 = new Zi3();
fun(zi3);
int i = 10;
fun(i);
}
public static void fun(int a) { // int a = 10;
}
// ****************************************************************
// 方法的参数列表是父类, 可以传入所有子类的对象
public static void fun(Fu fu) { // Fu fu = new Zi1();
// Fu fu = new Zi2();
// Fu fu = new Zi3();
fu.fun();
}
// ****************************************************************
}
总结:
- 方法的参数列表是父类(接口), 那么可以传入它们所有子类的对象
3. 向上转型和向下转型(结合代码理解)
(1) 多态的弊端
- 多态中使用父类的引用, 不能直接使用子类特有的属性和行为.
(2) 向上转型和向下转型
向上转型
- 对应基本数据类型的: 隐式类型转换
double d = 100;
Animal a = new Dog();
向下转型
- 对应基本数据类型的: 强制类型转换
- (int) d
- (Dog) a
(3) instanceof关键字
- 使用格式
A instanceof B : 判断A是否是B类型
是: true
不是: false