接口

JAVA 面向对象

接口
需求:需要飞到北京出差
飞机、鸟和超人不能归于一个类属,但是具备有相同的特性:会飞的。所以引入了一个新概念叫做接口,可以用于规范实现接口的类中必须实现接口中抽象方法。接口可以理解为一种契约
使用关键字interface定义接口

1public interface 会飞的 {
2 public void 起飞();
3 public void 巡航飞行();
4 public void 降落();
5//没有具体实现,也无法定义具体实现,这里是抽象方法
}

抽象类中的抽象方法不能省略abstract关键字,但是接口中的方法声明可以添加abstract,也可以不写
接口不能直接使用,必须有对应的实现类

1public class 飞机类 implements 会飞的 {
//共性是通过实现接口来表示的
2 private String name; //名称,这是类属的属性,这里可以定义字节类的成员,和接口无关
3 //如果当前类不是抽象类,则必须实现接口中的所有抽象方法
4 public void 起飞() {
5System.out.println("使劲的跑,一抬头就飞起来了");
6 }
7 public void 巡航飞行() {
8System.out.println("使劲的烧油...");
9}
10public void 降落() {
11System.out.println("我对准...");
12
13}
}

通过接口定义变量,使用具体类的实例,进行调用

1 会飞的 obj = new 飞机类();
2 obj.起飞();
//飞机类中必须提供接口中的所有抽象方法的实现,否则类只能是抽象类
//因为变量是通过接口进行声明的,所以只能调用接口中声明的方法,不能直接调用实现类中的没有在接口中声明过的方法
3 obj.巡航飞行();
4 obj.降落();

引入接口的目的在于隔离实现

1 public void 出差(飞机 obj){}
2 这种写法当前类和飞机是耦合的,如果需要坐超人出差,则必须修改源代码
3
4 public void 出差(会飞的 obj){}
5 当前类只是和接口耦合,任何实现了接口的对象都可以作为参数进行传入

使用接口而不是使用具体的类,则可以实现在实现接口的多个具体实现类之间进行更换,例如定义出超人类
什么是接口
在Java中不直接支持多继承,因为会出现调用的不确定性,所以Java将多继承机制进行改良,在Java中变成了多实现。一个类只能有一个直系双亲类,一个类可以实现多个接口,一个接口可以继承多个接口

1 interface IA{}
2 interface IB{}
3 interface IC extends IA,IB{}正确的,其中IC中的方法等于IA+IB
4
5 class A implements IA,IB{}
6 IA a=new A();
7 IB b=new A();

没有构造器方法,不能定义静态或者非静态代码块

1 public interface IA{
2 public IA(){}
3//语法报错
}

没有属性,只能定义常量

1public class Test {
2public static void main(String[] args) {
3System.out.println(IA.name);
4System.out.println(B.name);
5
6
//常量可以直接使用
//实现类也可以直接访问常量
}
}
7
8interface IA {
9//private int age;语法报错,提示信息为Illegal modifier for the interface field
IA.name; only public, static & final are permitted
10String name = "yanjun";// 接口中只能定义常量,不能定义属性,默认限定词public staticfinal,自定义限定词不能冲突
11}
12
13class B implements IA{}
//访问常量既可以通过接口IA和实现类B名称的方式直接访问,例如B.name。也可以通过B对象的方式进行访,例如new B().name

可以包含抽象方法,也可以没有抽象方法

1 interface IA1 {
2 }// 这个接口中没有包含任何抽象方法。如果一个接口中没有定义抽象方法,这种接口也叫做旗标接口、标志接口
3
4 class A1Impl implements IA1 {
5 }
1interface IA2{//接口的限定词同类定义一致
2 int ee();//抽象方法,默认public abstract int ee();
3 public void pp();//方法的限定词可以是public, abstract, default, static,前面的public可以省略,如果不写默认public
4 public abstract void cc();//这里abstract可以省略,默认就是abstract
5 //在JDK1.8中引入特殊关键字default,允许在接口中提供方法的默认实现
6 public default void dd(){
//这个方法的调用时必须有实现类,否则无法创建对象,例如newIA()语法错误,也允许在实现类中覆盖定义
7System.out.println("dddd....");
8 }
9 //在JDK1.8中允许在接口中定义静态方法
10public static void ff(){
//这个静态方法可以通过接口名称直接调用在实现类中重新定义,但是不能通过IA2 a=new AImpl();
11
a.ff()的方式进行调用
System.out.println("ffffff");
12
13IA2.ff(),同时允许
}
}

接口允许多重继承,也允许一个类实现多个接口

1 public class Person {
2 public static void main(String[] args) {
3 IC cc=new CImpl();
4 cc.pp();
5 }
6 }
7 interface IA{
8public default void pp() {
9System.out.println("this is IA.pp() default");
10
11}
}
12
13interface IB{
14public default void pp() {
15System.out.println("this is IB.pp() default");
16}
17 }
18 //因为在两个父接口中都定义了pp方法的默认实现,则在子接口无法确定到底使用哪个,所以要求子接口必须明确说明
19interface IC extends IA,IB{
20 @Override
21 default void pp() {
22 System.out.println("this is IC.pp() default");
23 IA.super.pp();//调用IA接口所定义的pp方法
24 IB.super.pp();
25}
26 }
27 class CImpl implements IC{}
1 public class Person {
2 public static void main(String[] args) {
3 IA cc=new CImpl();
4 cc.pp();
5 }
6 }
7 interface IA{
8public default void pp() {
9System.out.println("this is IA.pp() default");
10
11}
}
12
13interface IB{
14public default void pp() {
15System.out.println("this is IB.pp() default");
16}
17 }
18 //报错的原因是IA和IB接口中有相同的方法定义,同时又有默认实现,则CImpl类不知道使用哪个默认实现,所以要求类中必须明确说明
19class CImpl implements IA,IB{
20
21 @Override
22 public void pp() {
23 System.out.println("可以定义自己的逻辑");
24 IA.super.pp();//也允许调用某个接口中的默认实现
25IB.super.pp();
26
27
}
}

抽象方法必须在实现类中提供实现

1class A2Impl implements IA2{
//在实现类中必须实现接口中的所有抽象方法,否则当前类只能是抽象类
2 public int ee() {
3 return 0;
4 }
5 public void pp() {
6System.out.println("A2Impl....");
7 }
8 public void cc() {
9System.out.println("A2Impl.....");
10}
11//dd方法由于在接口中有默认实现,所以可以不用重新定义,也允许重新定义
12}

可以使用default关键字给抽象方法提供默认实现,有默认实现的方法在实现类中可以重新定义,也可以不重新定义
报错原因:Java中不支持类的多重继承,一个类只能有一个双亲类
接口允许多重继承
一个类在继承另一个类的同时,还可以实现多个接口

1 public class Person {
2 public static void main(String[] args) {
3 IA a1=new AImpl();
4 B a2=new AImpl();
5 a1.pp();
6 }
7 }
8 interface IA{
9
10public void pp();
}
11
12class B {
13public void pp() {
14System.out.println("this is B.pp()");
15}
16 }
17 class AImpl extends B implements IA{
18 }
1 public class Person {
2 public static void main(String[] args) {
3 IA a1=new AImpl();
4 a1.pp();
5 IB a2=new AImpl();
6a2.pp();
7 }
8 }
9 interface IA{
10public void pp();
11}
12
13interface IB {
14public default void pp() {
15System.out.println("this is B.pp()");
16}
17 }
18 class AImpl implements IA,IB{
//不能因为IB中针对pp方法提供了默认实现,所以不在实现类中定义pp方法
19 @Override
20 public void pp() {
21System.out.println("添加的新的处理逻辑");
22//IA.super.pp();因为IA接口中并没有提供pp的默认实现,所以不允许这样调用IB.super.pp();
24}
25}

接口允许多重继承

1interface IA1{
2public void p1();
3 }
4 interface IA2{
5public void p2();
6}
7
8interface IC extends IA1,IA2{
9public void p3();
10//继承父接口的同时也允许自定义方法
}//可以继承多个父接口,此时IC中实际有3个抽象方法

类是单根继承,不允许继承多个父类
允许一个类实现多个接口,但是每个接口的抽象方法都必须提供实现,否则是抽象类。提供的实现也可以是继承

1public class A1{
2public void p1(){}
3 }
4 public class A2 extends A1 implements IA1,IA2{
5
6public void p2(){}
}
7
8public abstract class A3 extends A1 implements IA1,IA2{}//因为p2方法没有实现

接口的出现避免了单继承的局限性,这样定义C接口则拥有A+B的所有定义,可以使用A和B接口以及父类D声明变量类型,直接new T。但是约束时,用谁声明变量编译器系统识别就是谁这种类型,也就意味只能调用识别类型中的方法,不能调用其他方法

1interface A{
2public void p1();
3 }
4 interface B{
5public void p2();
6 }
7 interface C extents A,B{}
8
9class D{
10public void abc(){}
11 }
12 class T extends D implements C{
13public void p1(){}
14
15public void p2(){}
}
16
17 D d=new T();这里只能直接调用abc方法,如果使用其他方法则需要进行类型转换
18 A a=new T();这里只能直接调用A接口中声明的方法p1
19 B b=new T();这里只能直接调用B接口中声明的方法p2
20 C c=new T();

声明接口的语法

1访问修饰符 interface 接口名{}一般建议接口名称使用形容词

如果定义public接口,则规则和定义public类一致,要求接口名称和文件名称一致
外部的接口只能使用public、默认这两个范围限定词;如果定义内部接口则可以使用4大范围限定词
接口实际上提供了同一的操作界面(方法),如果是JDK1.8-版本则一个方法也不实现,等待某类或某几个类去实现它的方法【接口中的所有方法必须是抽象的】。如果使用的是JDK1.8+允许使用default在接口中定义默认实现,这个实现允许在实现类中重新定义覆盖

1public class Test1 {
2public static void main(String[] args) {
3 IA2 a2=new A2Impl();
4 a2.pp();
5
6}
}
7
8
9interface IA2 {
default void pp(){ //通过defaul在接口中定义方法的默认实现,则在实现类中可以覆盖定义,也可以继承使用
10 System.out.println("this is pp....");
11 this.ff();
12}
13
14void ff();
}
15
16class A2Impl implements IA2{
17public void ff() {
18System.out.println("this is ff...");
19
20}
}

default默认方法实现使用的限制

1public class Test1 {
2public static void main(String[] args) {
3IA2 a2 = new A2Impl();
4a2.pp();
5}
6 }
7 interface IA2 {
8default void pp() {
9System.out.println("this is No2 pp....");
10}
11 }
12 interface IA3 {
13default void pp(){
14System.out.println("this is No3 pp");
15}
16 }
17 class A2Impl implements IA2, IA3 {//如果IA2中有一个default实现的方法和IA3中的方法一致,则必须在实现类中重新定义
18public void pp() {
19 IA2.super.pp();//调用IA2接口中的pp方法的默认实现
20 IA3.super.pp();
21
22
}
}

接口中没有属性,只能定义常量,它提供一些常量,实现它的类可以共享这些常量
接口可以给出访问控制符,用public修饰的是公共接口,到处可见;如果定义接口没有范围限定词,则只能在同包中访问
接口中只能定义常量和抽象方法
这是JDK1.8以前版本的规则,不是最新的
接口中只能定义公共的常量,接口中的属性默认是public static nal类型的,必须是public static nal类型的

1interface IA{
2String name="yanjun";//这里实际上是常量定义,不是属性,它的限定词是public static final
String name="yanjun",必须在声明的同时进行赋值
3 }
4 //在接口中不能定义静态块
5 //接口中不能定义构造器  static{}

接口中只能定义公共的抽象方法, 只有在JDK1.8+中可以使用default关键字定义方法实现。接口中的方法默认是public abstract类型的,而且必须是public abstract类型的。只有在JDK1.8+中可以使用default关键字定义方法默认实现,同时允许在实现类中覆盖重新定义
接口不能被实例化,只能通过实现类所实现,但是可以用于声明变量的类型。

接口 变量名=new 实现接口类();

接口没有构造函数
接口中的抽象方法必须在非抽象子类中提供实现,这个实现可以是继承来的

1interface IA2 {
2public void pp();
3}
4
5class A2 {
6 public void pp() {
7 }
8}
9
10 class B2 extends A2 implements IA2 { //这里的pp方法的实现是从父类中继承来的
11 }

一个类实现接口的语法

1class 类名称 implements 接口名称{
}

接口抽象方法的默认修饰符为public,在实现接口时必须用public关键字在方法头上说明

1interface IA2 {
2void pp();
3 }
4 class B2 implements IA2 {
5 void pp() {
6 }
7//语法报错,因为IA2接口中的方法为public abstract
}

一个接口可以被多个子类实现。一个子类还可以实现多个接口
类实现接口
一个类在实现某接口的抽象方法时,必须使用完全相同的方法头public
如果一个类实现多接口,用逗号隔开
如果一个类实现了声明相同方法的两个接口,则被多个接口共用

1public class Test1 {
2public static void main(String[] args) {
3 IA2 a2=new B2(); a2.pp();
4 IA3 a3=new B2(); a3.pp();
5}
6 }
7 interface IA2 {
8
9void pp();
}
10 interface IA3{
11 void pp();
12 }
13 class B2 implements IA2,IA3 {
14public void pp() {
15System.out.println("this is B2.pp()");
16
17
}
}

类在实现接口时可以定义它自己的附加成员,这也是最常见的形式

1public class Test1 {
2public static void main(String[] args) {
3 IA2 a2=new B2();
4 a2.pp();//这里不能直接调用B2实现类中的其它方法,如果需要调用则应该进行强制类型转换
5 ((B2)a2).dd();
6
7}
}
8
9interface IA2 {
10
11void pp();
}
12
13 class B2 implements IA2 {
14 public void pp() {
15
16System.out.println("this is B2.pp()");
}
17
18 private int age=100;
19 public void pp(int k){
20
21System.out.println("this is pp(int)");
}
22public void dd(){
23System.out.println("this is dd()");
24
25}
}
26

如果一个类不完全实现接口的所有方法,必须把类定义成abstract类型的类,任何继承该类的子类必须实现该接口
接口中常量
可以为多个接口的实现类共享常量

1public class Test1 {
2public static void main(String[] args) {
3 System.out.println(IA2.PI);//可以直接使用
4 A3 a=new A3();
5 a.setR(4);
6System.out.println(a.getArea());
7}
8 }
9 interface IA2 {
10double PI=3.1415;
11 } 
12 class A3 implements IA2{
13 private double r;
14 public double getArea(){
15
//在实现类中也可以直接使用
return PI*r*r;
16 }
17 public void setR(double r) {
18this.r = r;
19
20
}
}

只需在接口中定义并赋值,此后不能再修改
在类中说明是接口的实现类,就可以使用该接口的常量了
一个对象往往有多重身份
Java中一个子类只能继承一个父类 (不能表示)
java中一个类可以实现多个接口。(可以表示)

1class 类名称 implements 接口1,接口2, ... {}

通过继承和运行时多态的双重机制,可以定义一个被很多不同却有关的对象类型的运用的一致的接口
维持抽象接口,甚至不需要重新编译,就可以调用新类的实例

1public void 出差(会飞的obj){obj.起飞(); ...}
2
3 调用的时候可以传入不能类型的对象
4 出差(new 飞机());--- 出差(new());

接口的特殊特征
一个类只能有一个父类!
一个类可以实现多个接口!
一个接口可以继承多个接口!

1interface 接口名 extends 接口名称1 ,父接口名称2 , ...{}

接口的作用
统一访问
解耦 通过接口可以隔离具体实现
解耦就是 在使用者 和 实现者 之间没有关系。 无论实现者如何改变实现,对于使用者使用不会变化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值