总结

接口

接口的定义

  • 用关键字interface来声明一个接口
  • 接口中只能有两样东西: 常量和抽象方法
1
2
3
4
5
6
7
8
9
10
[public] interface 接口名 {  

//常量声明
[public] [static] [final] <变量类型> <变量名> = <值>;
...

//抽象方法声明
[public] [abstract] <返回类型> 方法名(参数列表);
...
}
  • 接口中的抽象方法和常量不是必须都有, 甚至两者都没有也可以
  • 和抽象类一样, 接口不能用来创建对象实例
  • 接口和抽象类一样, 不能用来创建实例
  • 在接口中如果有变量声明, 那么该变量一定由public、final、static修饰, 没有的话系统在编译时也会默认加上
  • 接口中声明的变量一定是公有的静态常量, 可以通过接口名访问
  • 接口中final常量必须在定义时初始化, 初始化时可以使用常量表达式或非常量表达式
  • 在接口中声明的方法一定由public和abstract修饰, 没有的话系统在编译时也会默认加上, 所以一定是公有的抽象方法.

接口的实现

  • 一个类通过关键字implements声明自己实现了一个或多个接口
  • 如果实现了多个接口, 用逗号分隔接口名
1
2
3
4
5
6
7
[修饰符] class 类名 implements 接口1, 接口2, ... {
//接口方法的实现
...

//实现类新增的内容
...
}
  • 一个类实现某个接口也就是要实现该接口的所有抽象方法
  • 如果只实现了一部分, 则接口未被实现的那些抽象方法会被实现类所继承, 从而成为抽象类
  • 实现类继承接口的常量, 成为自己的静态常量, 既可以通过接口名访问, 也可以通过类名访问, 还可以通过实现类的对象访问
  • 在实现类中实现接口的抽象方法时, 必须使用完全相同的方法原型, 并且不能降低方法的访问权限, 因而实现类所实现的方法权限必须是public.
  • 有些接口没有声明任何方法, 这种接口叫做标识接口
  • 标识接口仅仅充当标识的作用, 用来表明实现它的类属于某个特定的类型
1
2
3
[修饰符] class 类名 extends 父类名 implements 接口1, 接口2, ... {
...
}

接口的继承

1
2
3
4
[public] interface 接口名 extends 父接口1, 父接口2, ... {
//新增的抽象方法或静态常量
...
}
  • 一个接口可以继承一个或多个接口, 从而继承其它接口的抽象方法和常量
  • 实现类除了实现当前接口自己定义的抽象方法, 还要实现该接口继承而来的抽象方法
  • 如果在子接口中声明了和父接口同名的常量或原型相同的方法, 则父接口中的常量被隐藏, 方法被重写(覆盖).
  • 如果实现类是非abstract类, 则该类必须实现接口的所有抽象方法, 否则未被实现的抽象方法会被实现类所继承, 从而只能是abstract类
  • 如果实现类是abstract类, 则该类可以只实现接口的一部分抽象方法.当然, 即使实现类全部实现了接口的抽象方法, 也可以是抽象类
  • 如果父类实现了某个接口, 则子类会继承父类的接口实现, 相当于子类也实现了这个接口.

接口类型

  • 接口也是一种引用数据类型, 可以当作数据类型使用
  • 可以用接口来声明变量, 也可以把一个实现类的对象赋值给接口变量, 这也是上转型

接口回调

接口回调是指把实现类的对象赋值给接口变量, 然后通过接口变量访问接口方法

1
2
接口类型 接口变量 = 用实现类创建的对象;        
接口变量.接口方法([参数列表]);

通过接口变量来访问接口方法时, 由于不同的实现类对同一方法有不同的实现, 从而表现出多态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface A{
void p();
}

class B implements A{
@Override
public void p(){
System.out.println("Hello");
}
}

public class C{
public static void main(String []args){
A a;
a = new B();
a.p(); // 接口回调调用实例方法
}
}

接口做参数

如果一个方法的形参是接口类型, 就可以将实现类的对象传给这个参数, 这也是上转型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
interface A{
void p();
}

class B implements A{
@Override
public void p(){
System.out.println("Hello");
}
}

public class C{

// 接口做参数
public void f(A a){
a.p();
}

public static void main(String []args){
C c = new C();
c.f(new B()); // 类的对象传给接口参数
}
}

instanceof运算符

  • 功能: 判断一个对象是否是某个类的实例, 或者一个对象是否实现了某个接口

  • 格式: 对象 instanceof 类或接口

  • 结果: true 或 false

  • instanceof操作符的前值是一个对象, 后值是一个类或接口.

  • 如果前值对象是后值类的对象实例, 或者可以上转型(或下转型)为后值类的对象实例, 或者实现了后值接口, 则结果是true;否则是false

  • 子类对象可以当作父类对象, 如果instanceof的前值是子类对象, 后值是父类, 则结果是true

  • 一个类实现了子接口, 那么也就实现了父接口, 如果instanceof的前值是实现类对象, 后值是当前接口的父接口, 则结果也是true

多态总结

  • 多态是指在程序中相同的名称表现出不同的行为, 包括静态多态和动态多态两种.
    • 静态多态一般指方法重载
    • 动态多态也称为运行时多态
      1. 实现继承, 或实现接口
      2. 子类重写父类方法, 或实现类实现接口的方法)
      3. 执行上转型, 通过上转型对象访问父类被重写的方法, 或接口被实现的方法