接口的细节
- 1、接口中的变量
- 2、接口的继承
- 3、类的继承与接口
- 4、instanceof
- 5、使用接口替代继承
- 6、Java 8和Java 9对接口的增强
1、接口中的变量
接口中可以定义变量,语法如下所示:
publicinterfaceInterface1{publicstaticfinalinta=0;}这里定义了一个变量int a,修饰符是public static final,但这个修饰符是可选的,即使不写,也是public staticfinal。这个变量可以通过“接口名.变量名”的方式使用,如Interface1.a。
2、接口的继承
接口也可以继承,一个接口可以继承其他接口,继承的基本概念与类一样,但与类不同的是,接口可以有多个父接 口,代码如下所示:
publicinterfaceIBase1{voidmethod1();}publicinterfaceIBase2{voidmethod2();}publicinterfaceIChildextendsIBase1,IBase2{}3、类的继承与接口
类的继承与接口可以共存,换句话说,类可以在继承基类的情况下,同时实现一个或多个接口,语法如下所示:
publicclassChildextendsBaseimplementsIChild{//主体代码}关键字extends要放在implements之前。
4、instanceof
与类一样,接口也可以使用instanceof关键字,用来判断一个对象是否实现了某接口,例如:
Pointp=newPoint(2,3);if(pinstanceofMyComparable){System.out.println("comparable");}5、使用接口替代继承
继承至少有两个好处:一个是复用代码;另一个是利用多态和动态绑定统一处理多种不同子类的对象。
使用组合替代继承,可以复用代码,但不能统一处理。使用接口替代继承,针对接口编程,可以实现统一处理不同类型的对象,但接口没有代码实现,无法复用代码。将组合和接口结合起来替代继承,就既可以统一处理,又可以复用代码了。
先增加一个接口IAdd,代码如下:
publicinterfaceIAdd{voidadd(intnumber);voidaddAll(int[]numbers);}修改Base代码,让它实现IAdd接口,代码基本不变:
publicclassBaseimplementsIAdd{privatestaticfinalintMAX_NUM=1000;privateint[]arr=newint[MAX_NUM];privateintcount;publicvoidadd(intnumber){if(count<MAX_NUM){arr[count++]=number;}}publicvoidaddAll(int[]numbers){for(intnum:numbers){add(num);}}}修改Child代码,也是实现IAdd接口,代码基本不变:
publicclassChildimplementsIAdd{privateBasebase;privatelongsum;publicChild(){base=newBase();}publicvoidadd(intnumber){base.add(number);sum+=number;}publicvoidaddAll(int[]numbers){base.addAll(numbers);for(inti=0;i<numbers.length;i++){sum+=numbers[i];}}publiclonggetSum(){returnsum;}}Child复用了Base的代码,又都实现了IAdd接口,这样,既复用代码,又可以统一处理,还不用担心破坏封装。
6、Java 8和Java 9对接口的增强
需要说明的是,前面介绍的都是Java 8之前的接口概念,Java 8和Java 9对接口做了一些增强。在Java 8之前,接口中的方法都是抽象方法,都没有实现体,Java 8允许在接口中定义两类新方法:静态方法和默认方法,它们有实现体,比如:
publicinterfaceIDemo{voidhello();publicstaticvoidtest(){System.out.println("hello");}defaultvoidhi(){System.out.println("hi");}}test()就是一个静态方法,可以通过IDemo.test()调用。在接口不能定义静态方法之前,相关的静态方法往往定义在单独的类中,比如,Java API中,Collection接口有一个对应的单独的类Collections,在Java 8中,就可以直接写在接口中了,比如Comparator接口就定义了多个静态方法。
hi()是一个默认方法,用关键字default表示。默认方法与抽象方法都是接口的方法,不同在于,默认方法有默认的实现,实现类可以改变它的实现,也可以不改变。引入默认方法主要是函数式数据处理的需求,是为了便于给接口增加功能。
在没有默认方法之前,Java是很难给接口增加功能的,比如List接口,因为有太多非Java JDK控制的代码实现了该接口,如果给接口增加一个方法,则那些接口的实现就无法在新版Java上运行,必须改写代码,实现新的方法,这显然是无法接受的。函数式数据处理需要给一些接口增加一些新的方法,所以就有了默认方法的概念,接口增加了新方法,而接口现有的实现类也不需要必须实现。看一些例子,List接口增加了sort方法,其定义为:
defaultvoidsort(Comparator<?superE>c){Object[]a=this.toArray();Arrays.sort(a,(Comparator)c);ListIterator<E>i=this.listIterator();for(Objecte:a){i.next();i.set((E)e);}}Collection接口增加了stream方法,其定义为:
defaultStream<E>stream(){returnStreamSupport.stream(spliterator(),false);}在Java 8中,静态方法和默认方法都必须是public的,Java 9去除了这个限制,它们都可以是private的,引入private方法主要是为了方便多个静态或默认方法复用代码,比如:
publicinterfaceIDemoPrivate{privatevoidcommon(){System.out.println("common");}defaultvoidactionA(){common();}defaultvoidactionB(){common();}}这里,actionA和actionB两个默认方法共享了相同的common()方法的代码。