Interface
Interface
与class
,abstract
并称面向对象三巨头。
interface:抽象——分类学上无关联的(不同种不同类)事物间的相同特征(一般为方法)
class:抽象——分类学上相关联的(同种同类)事物间的相同特征(属性+方法)
abstract:抽象——相较class更高层次的/更加本质的(同类)相同特征(属性+方法)
简单举个例子:
abstract:人类
class:中国人,美国人,日本人
interface:吃,睡,动
class 2:狗,猫,兔
界限很清晰。狗猫兔与中国人美国人日本人不是同一类——人类。
但也能吃,睡,动。也就是中国人美国人日本人与狗猫兔都可以实现吃、睡、动三个接口。
理解
interface是一个形容词,形容不同种类事物拥有某一共同特征
拥有同一种类能力的、特性的、行为的…或,遵循同一种类规则、协议的
是一种特殊的分类形式,片面的,只考虑实现类是否有某一特征,而不考虑全面的
作用
①绕开继承限制 == 解耦继承关系
实质:不需要继承父类的全部实例成员方法成员属性,也不用再走父类构造器
②实现多继承的效果
实质:一个类可实现多个接口
③实现类的多态性【新的引用类型】
实质:interface、abstract、class这三是一个体系的,都是对事物的抽象
官方定义
接口:一种新的引用类型
注:不能直接实例化,只能实例化接口的实现类
成员:5种成员【!!!只有这5种,没有静实初始化器,也没有构造器】
嵌入类,嵌入接口,静态常量变量,抽象实例方法(没有实例变量),静态类方法
分类:3种接口
接口:
普通接口 (normal interface)
|-①嵌入接口 (nested interface)
|-②顶级接口 (top level interface)
③注解类型 (annotation types)
类实现接口:class IC implements InterfaceTypeList
注:实现类会继承接口的static final变量,可直接调用,当然也可以被实现类的静实变量覆盖。
接口继承接口:ExtendsInterfaces extends InterfaceTypeList
注:InterfaceList以,
逗号隔开,不能写多个implements
接口的修饰符
public,protected、private仅为(non-static)成员接口使用,由类声明。顶级接口缺省值为public
static嵌入接口,strictfp严格数据类型,@注解类型修饰符
泛型接口
格式:泛型参数以< >
标识,type-param-list以,
分割,
interface interface-name < type-param-list > {...}
注1:泛型接口的实现类也必须是泛型
class class-name <type-param-list> implements interface-name<type-arg-list> {...}
注2:如果实现的是一个特定类型的泛型接口,则不需要是泛型
class MyClass implements MinMax<Integer> {...}
特性
接口特性
- 接口只可extends接口(但没有构造器),不能继承类;可以被类实现,但不能被类继承。
- 接口中只有下述五种成员
①default/public abstract { 可定义局部内部类 } 抽象、默认方法(public abstract可省)
②static interface 静态嵌入接口 (static可省)
③static class 静态嵌入类(static可省)
④public static final 静态常量变量(public static可省)
⑤static method 静态类方法(必须写方法体) - 接口可被abstract类实现,且可不实现接口抽象方法,但在其非抽象子类必须实现所有抽象方法
- 子接口从父接口继承所有成员,除了类和接口(均被默认的static修饰——嵌入);可复写方法
- 父类A子类B,允许同时显式实现接口I。但必须是相同泛型
接口成员函数特性
- 接口实例抽象方法抛出异常范围必须大于实现类复写方法抛出异常范围(实现类只能更精确)
- 接口静态方法不能被继承、不能通过其实现类调用,只能通过
接口名.staticMethod()
调用 abstract
,default
,static
不能同时修饰接口方法strictfp
修饰符的不会影响覆盖方法的规则- 接口的匿名内部类中、接口的default函数中可使用this,super。
- 父接口的实例抽象方法不得被子接口static静态方法复写(必须同函数签名返回值类型),也就是子静态方法不能隐藏父实例
- an interface declares two public methods with the same name , and a subinterface overrides one of them, the subinterface still inherits the other method.【当出现重复继承同一个间接/直接SuperInterface,那么只要在继承链上有一个子类接口实现了(通过default)SuperInterface公共方法,那么就以子类复写的为准。而不是以SuperInterface的default方法为准】
- 多继承的时候出现重复的抽象方法是允许,因为他们最终都会被实现为一个具体方法,如果有重复的default方法会编译报错,当实现类Override两接口重复的default方法后,编译通过。注意在实现类中仍可调两接口的冲突方法通过
I1.super.defaultTest();I2.super.defaultTest();
仍然是继承了。
接口成员变量特性
- 接口的static final 常量会被实现类/子接口继承,也可以被实现类实例变量、静态变量覆盖
- 接口的Field必须进行初始化,否则编译错误
- 接口静态常量变量的初始化设定式不得有this与super
- 如果Fields, methods, and member types of an interface type继承有重复冲突可用接口名限定
还有两个没看懂的。求大佬来解惑
It is a compile-time error to refer to a type parameter of an interface I anywhere
in the declaration of a field or type member of I.
It is a compile-time error to use the name of a type parameter of any surrounding
declaration in the header or body of a static method of an interface.
接口的多态性
文字案例
排序类中的排序方法接受的参数是——Comparable接口类型 数组
对于排序类来说,他只关注如何多个可比较对象的排序,而不关注两个可比较对象如何比较。即不需要考虑具体类的两实例比较方法,只需实现Comparable接口的对象数组内部对象的排序算法即可。
实质上——将多个实例对象排序算法与两实例对象比较方法 解耦。【将排序与比较解耦】
只要是可比较的/拥有比较能力的事物,排序类就可以对这同一类可排序的事物进行排序。
代码案例
①子类对象拥有 其实现接口的 多种形态
/********接口s********/
interface Runner { void run(); }
interface Swimmer { double swim(); }
/********接口s实现类********/
class Man extends Creator implements Runner, Swimmer {
//实现接口中的抽象方法
@Override
public void run() { System.out.println("跑了1000m..."); }
//实现接口中的抽象方法
@Override
public double swim() { return 1000; }
}
public class Test {
public static void main(String args[]) {
//接口s实现类实例对象
Man man = new Man();
//同一实现类具有多个行为、特征
run(man);
swim(man);
}
//将man实现类实例对象 塑形为 Runner接口类型对象
static void run(Runner r) { r.run(); }
//将man实现类实例对象 塑形为 Swimmer接口类型对象
static void swim(Swimmer s) { System.out.println("游了"+s.swim()+"m..."); }
}
//console
跑了1000m...
游了1000.0m...
②接口与其多个实现类之间存在多态性
/********接口********/
interface Runner {
void run();
}
/********实现类s********/
class Man implements Runner {
@Override
public void run() {
System.out.println("Man跑10m/s...");
}
}
class Tiger implements Runner {
@Override
public void run() {
System.out.println("Tiger跑100m/s...");
}
}
class SportsCar implements Runner {
@Override
public void run() {
System.out.println("SportsCar跑500m/s...");
}
}
public class Test {
public static void main(String args[]) {
//实现类s
Man man = new Man();
Tiger tiger = new Tiger();
SportsCar sportsCar = new SportsCar();
//同一个行为、特征的不同表现
run(man);
run(tiger);
run(sportsCar);
}
//多个实现类 塑形为 同一个Runner接口类型对象
static void run(Runner r) {
r.run();
}
}
//console
Man跑10m/s...
Tiger跑100m/s...
SportsCar跑500m/s...
③泛型接口案例【转载 W3cschool Java泛型教程 实例代码】
interface MinMax<T extends Comparable<T>> {
T max();
}
class MyClass<T extends Comparable<T>> implements MinMax<T> {
T[] vals;
MyClass(T[] o) {
vals = o;
}
public T max() {
T v = vals[0];
for (int i = 1; i < vals.length; i++) {
if (vals[i].compareTo(v) > 0) {
v = vals[i];
}
}
return v;
}
}
public class Main {
public static void main(String args[]) {
Integer inums[] = { 3, 6, 2, 8, 6 };
Character chs[] = { "b", "r", "p", "w" };
MyClass<Integer> a = new MyClass<Integer>(inums);
MyClass<Character> b = new MyClass<Character>(chs);
System.out.println(a.max());
System.out.println(b.max());
}
}
//console
8
w
略·注解
-
特殊的接口——注解(后面详解)
-
标记接口:没有任何方法和属性的接口.
它仅仅表明实现它的类属于一个特定数据类型
例如: java.io.Serializable(可序列化、可反序列化的类)主要用于三种目的
- 建立一个公共的父接口:
- 使用一个标记接口来建立一组接口的父接口
- 向一个类添加数据类型
- 实现标记接口的类不需要定义任何接口方法,但该类可通过多态性塑形成一个接口类型
- 简化赋值性代码
- 建立一个公共的父接口: