我学习 B站 韩顺平 老师课程的学习笔记

接口

主要包含关键字:
interface
implements
default

接口基本规则

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
public interface Ainterface {
//可以有属性
//1、属性只能用public修饰
//2、属性定义时就要赋值,因为是final
//3、可以使用static、final关键字修饰
public int n1 = 10;
public static int n2 = 10;
public final int n3 = 10;
public final static n4 = 15;
//实际上不论怎么定义在接口中的属性都是public static final修饰的

//可以有方法(1)抽象方法 (2)默认实现方法(显示使用default关键字) (3)静态方法
//在java8之前只能有抽象方法
//这里的抽象方法不需要abstract关键字
//只能用public修饰
//抽象方法都不能使用final、static来修饰
public void hi();
//在Java8之后方法可以有方法体了
//但是必须要有default关键字修饰
public default void hi3(){
System.out.println("hi3()....");
}
//也可以用使用静态方法(不是抽象方法嘛)
public static void hi4(){
System.out.println("hi4()...");
}
}

使用接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AinterfaceTestDrive {
public static void main(String[] args) {
Test test = new Test();
//使用接口方法
test.hi();
test.hi3();
Ainterface.hi4();//hi4()是静态方法,对于接口来说只能通过接口名来调用
}
}
class Test implements Ainterface{
//必须要重写抽象方法,可以不重写已经定义了的方法

@Override
public void hi() {
System.out.println("hi()...");
}
}

接口使用细节

  1. 接口不能被实例化

  2. 接口中的方法是public方法,接口中的抽象方法,可以不用abstract修饰(实际上可以理解为abstract被隐藏了)(必须是public,但是如果在接口中省略public和平常的默认不一样,在接口中的默认相当于public)

  3. 一个普通类实现接口就必须将该接口的所有方法都实现(可以用alt+enter快速重写)

  4. 抽象类实现接口,可以不用实现接口的方法

  5. 一个类同时可以实现多个接口(变相的完成了多个继承)

  6. 接口中的属性都是final,而且是public static final修饰符(接口中的属性可以直接省略修饰符)

  7. 接口属性的访问形式:接口名.属性名(静态的)

  8. 接口不能继承其它类,但可以继承多个别的接口
    语法:

    1
    interface A extends B,C{}
  9. 接口的修饰符只能是public和默认,这和类的修饰符一样

  10. 一个类实现一个接口,相当于继承一个接口,可以调用接口中的属性
    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    interface A{
    int a = 23;
    }
    class B implements A{
    }
    ///main中:
    B b = new B();
    //下面三个语句都合法且结果都为23
    System.out.println(b.a);
    System.out.println(A.a);
    System.out.println(B.a);

实现接口和继承类

继承:当子类继承了父类,就自动拥有了父类的功能,如果子类需要扩展功能,就可以通过实现接口的方式扩展。可以理解实现接口时对java单继承机制的一种补充(但接口和继承还是有不一样的)

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.abstract_.interface_;

public class ExtendsVsInterface {
public static void main(String[] args) {
LittleMonkey1 littleMonkey1 = new LittleMonkey1("悟空");
littleMonkey1.climbing();
LitterMonkey2 litterMonkey2 = new LitterMonkey2("六耳猕猴");
litterMonkey2.climbing();
litterMonkey2.swimming();
litterMonkey2.flying();
}
}

class Monkey{
private String name;

public Monkey(String name) {
this.name = name;
}

public void climbing(){
System.out.println(name + " 会爬树...");
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
class LittleMonkey1 extends Monkey{
public LittleMonkey1(String name) {
super(name);
}
}
//小猴子继承大猴子,但是我想小猴子像鱼一样会游泳,像鸟一样会飞
// 定义一条鱼的接口
interface Fish_able{
String fish_name = "金鱼";
void swimming();
}
//定义一只鸟的接口
interface Bird_able{
String bird_name = "小鹰";
void flying();
}
//为了和前面的继承区别开,在弄一个小猴子类
class LitterMonkey2 extends Monkey implements Fish_able,Bird_able{//继承和实现接口同时使用的情况
public LitterMonkey2 (String name) {
super(name);
}

@Override
public void swimming() {
System.out.println(getName() + " 通过学习学会了像 " + Fish_able.fish_name + " 一样游泳...");
}

@Override
public void flying() {
System.out.println(getName() + " 通过学习学会了像 " + Bird_able.bird_name + " 一样飞翔...");
}
}

主要不同点

  • 接口和继承解决问题不同
    继承的价值主要在于:解决代码的复用性和可维护性
    接口的价值主要在于:设计,设计好各种规范(方法),让其他类去实现这些方法
  • 接口比继承更灵活
    继承时满足is-a关系(即要按常理思考能想得通的,比如小猴子继承大猴子活动大猴子的技能,猴子会飞时不和常理的),但是接口是like-a的关系(就可以让猴子学会飞)
  • 接口在一定程度上实现代码解耦
    即接口规范性+动态绑定就可以很好的解耦

接口的多态

  1. 多态参数
    接口可以实现多态参数,以接口为参数类型的接口函数可以使用接收实现了这个接口的类的实例作为参数。接口类性的变量可以指向实现了接口的对象实例
    例如:

    1
    2
    3
    4
    5
    6
    7
    interface IF {}
    class Master implements IF {}
    class Car implements IF {}

    //main中:
    IF if01 = new Master();
    if01 = new Car();

    也就是继承体现多态的向上转型
    同样也可以向下转型:同样的语法

    1
    2
    3
    if(if01 instanceof Car){//一定要先判断运行类型判断能不能转型
    if01 = (Car)if01;
    }
  2. 多态数组
    既然可以实现多态参数,也就是可以实现向上转型那么当然可以实现多态参数。在继承的多态数组中是以父类为编译类型,那么在这里就是以接口为编译类型了

1
2
3
4
5
6
7
8
interface USB {}
class Phone_ implements USB {}
class Camera_ implements USB {}

//main中:
USB[] usb = new USB[2];//第一两个大小的USB接口
usb[0] = new Phone_;//实现多态数组
usb[1] = new Camera_;//实现多态数组
  1. 接口的多态传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class InterfacePolyPass {
public static void main(String[] args) {
//接口类型可以指向实现接口的对象的实例
IG ig = new Teacher();

//如果只是实现IG没有实现IH按理来说是不能指向IG的对象的实例的,所以下面语句是会报错的
//但是如果使得IG继承IH,那么相当于Teacher也实现了IH,所以下面的语句又不会报错了
//这里就是接口的多态传递现象
IH ih = new Teacher();
}
}
interface IH {}
interface IG extends IH {}
class Teacher implements IG {}