接口

概述

接口是java中的一种引用数据类型,使用interface关键字表示,里面可以写常量抽象方法;

  • 在JDK7及以前只能写常量及抽象
  • 可以简单的把接口理解成一种规范, 谁实现了这个接口就要遵守该规范

JDK7以前

1
只能写常量和抽象方法;

JDK7以后

1
2
3
4
jdk8新增了默认方法和静态方法,jdk9新增了私有方法;
默认方法,是为了让所有的实现类对象,直接调用;
静态方法,是为了让调用者通过接口直接调用方法;(接口中的静态方法,不能通过实现类对象调用)
私有方法,是为了提升多个默认方法或多个静态方法中出现的共性内容的复用性;

为什么使用接口

1
接口相当于是"规范",让实现类实现接口之后,相当于"满足了某种规范",让调用者可以根据接口规范,调用实现类中的具体内容;

什么时候可以使用接口

1
任意类中只要有"方法",就可以针对方法,设计出接口;

如何编写接口

1
2
定义接口使用 interface;
类实现接口使用 implements;

image-20240117172416915

CodeDemo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Fly接口
public interface Fly {
int ABC = 123; // 省略了public Static关键字

void fly(); // 省略了public abstract
}


// 实现类
public class Bird implements Fly{
@Override
public void fly() {
System.out.println("鸟在飞");
}
}


// 测试类
public class Test {
public static void main(String[] args) {
// 尝试创建接口对象
// Fly f = new Fly(); // 不能直接创建对象

// 接口就是规范,只能找实现了这个规范的具体实现类(子类) 然后创建实现类对象使用即可
Bird b = new Bird();
b.fly();
System.out.println(Fly.ABC); // 这里说明了接口中的常量是public的
}
}

多态

多态的明显标志就是: 父类类型的变量 存了 子类类型的对象就叫多态

大前提:(3点)

  • 有继承或实现关系; 且父类对象引用子类对象; 且存在方法的重写

前提

  1. 有继承或实现;
  2. 有方法重写;
  3. 有父类类型的变量保存了子类类型的对象;

多态代码练习

这里注意几个点

  • 多态的三个前提
  • 多态的强制类型转换并不会改变对象的地址值(说白了转型来转型去还是一个对象)
  • 多态的对象保存的是子类重写父类后的方法(编译看左, 运行看右)
  • 对于成员变量来说, 是编译看左, 运行看左

image-20240118164559476

多态的好处

多态的好处体现在员工类(形参位置为Animal a) 的这个类, 实现了父类类型保存子类对象的用途.

从而进一步实现了每次传入一个子类对象就能调用执行子类重写的方法.

image-20240118165133334

CodeDemo

image-20240118170055556

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// Animal抽象类
public abstract class Animal {
public abstract void eat();
}


// Dog类-Animal子类
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃肉!");
}
}

// Cat类-Animal子类
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼!");
}
}

// Employee类(具体干活的类)
public class Employee {
/*
饲养动物的方法, 将来无论传递什么样的动物对象, 都能使用多态的形式调用eat方法
Animal a = new cat()
a.eat(), 执行的是子类的eat方法, 对于成员方法, 编译看左, 运行看右
*/
public void feed(Animal a){
a.eat();
}
// 如果使用了方法的重载, 根据传入什么动物就执行什么方法. 这种措施治标不治本.
}

// Boss类(指挥干活的类)
public class Boss {
public static void main(String[] args) {
// 1, 创建员工对象
Employee e = new Employee();
// 2, 创建动物对象
Cat c = new Cat();
Dog d = new Dog();
// 3, 面向员工对象, 让员工指挥动物吃饭
e.feed(c);
e.feed(d);
}
}

多态的弊端

不能使用多态的对象,调用与该状态无关的方法!

解决弊端的办法

1
利用强制类型转换,将多态形式的对象,转成子类本身类型即可;

避免强制类型转换异常的办法

1
2
3
4
5
6
7
8
9
10
11
使用 instanceof 关键字就可以判断对象的原始类型,然后再转即可;
例如:
public void siYangDongWu(Animal a){
// 判断 此时老板传递的动物是不是 Dog,如果是,则调用狗的看门的方法
a.eat();
// 可以利用 关键字 instanceof 判断多态的对象原始类型
if(a instanceof Dog){
Dog d = (Dog) a;
d.lookHome();
}
}

JDK8和9新特性

  • JDK < =7
    • 常量: 一般使用public Static final 修饰
    • 抽象方法: 意义就是增强实现类必须按这个方法声明完成功能
  • JDK==8
    • 新增了默认方法: 用default修饰(将)
      • 冲突: 如果多个接口中存在冲突的方法, 则要求子类直接重写方法
    • 新增了静态方法: 通过接口名直接调用, 提升代码的复用性
      • 冲突: 静态方法不存在冲突, 因为调用方式不允许通过子类对象调用, 只能通过接口名.方法名调用
      • 静态方法用途:
  • JDK >= 9
    • 新增了私有方法: 仅仅为了提升静态方法和默认方法的代码复用性
      • 冲突: 不会出现冲突, 因为用private修饰的方法, 外界根本调用不了

image-20240117182306243

image-20240117182358041