什么是接口?
接口不是类,而是对类的一组需求。
Java中的接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。 接口的两种含义:一,Java接口,Java语言中存在的结构,有特定的语法和结构;二,一个类所具有的方法的特征集合,是一种逻辑上的抽象。前者叫做“Java接口”,后者叫做“接口”。
Java接口的方法只能是抽象的和公开的,Java接口不能有构造器,Java接口可以有public,静态的和final属性。
接口把方法的特征和方法的实现分割开来。这种分割体现在接口常常代表一个角色,它包装与该角色相关的操作和属性,而实现这个接口的类便是扮演这个角色的演员。一个角色由不同的演员来演,而不同的演员之间除了扮演一个共同的角色之外,并不要求其它的共同之处。
与抽象类区别
Java接口和Java抽象类最大的一个区别,就在于Java抽象类可以提供某些方法的部分实现,而Java接口不可以,这大概就是Java抽象类唯一的优点吧,但这个优点非常有用。如果向一个抽象类里加入一个新的具体方法时,那么它所有的子类都一下子都得到了这个新方法,而Java接口做不到这一点,如果向一个Java接口里加入一个新方法,所有实现这个接口的类就无法成功通过编译了,因为你必须让每一个类都再实现这个方法才行,这显然是Java接口的缺点。
一个抽象类的实现只能由这个抽象类的子类给出,也就是说,这个实现处在抽象类所定义出的继承的等级结构中,而由于Java语言的单继承性,所以抽象类作为类型定义工具的效能大打折扣。在这一点上,Java接口的优势就出来了,任何一个实现了一个Java接口所规定的方法的类都可以具有这个接口的类型,而一个类可以实现任意多个Java接口,从而这个类就有了多种类型。
语法
定义接口
使用interface来定义一个接口。接口定义同类的定义类似,也是分为接口的声明和接口体,其中接口体由常量定义和方法定义两部分组成。定义接口的基本格式如下:
[修饰符] interface 接口名 [extends 父接口名列表]{
[public] [static] [final] 常量;[public] [abstract] 方法;
}
修饰符:可选,用于指定接口的访问权限,可选值为public。如果省略则使用默认的访问权限。
接口名:必选参数,用于指定接口的名称,接口名必须是合法的Java标识符。一般情况下,要求首字母大写。
extends 父接口名列表:可选参数,用于指定要定义的接口继承于哪个父接口。当使用extends关键字时,父接口名为必选参数。
方法:接口中的方法只有定义而没有被实现。
interface USB{ //int a;不能定义变量 //接口默认必须是public权限 //抽象方法,只能有声明不能有实现 public void usbread(); public void usbwrite(); /*public void print(){ System.out.println("sm"); }*/ /* USB.java:10: error: interface methods cannot have body public void print(){ ^ 1 error *///接口不能有实现部分的方法 }
实现接口
接口在定义后,就可以在类中实现该接口。在类中实现接口可以使用关键字implements,其基本格式如下:
[修饰符] class <类名> [extends 父类名] [implements 接口列表]{}
修饰符:可选参数,用于指定类的访问权限,可选值为public、abstract和final。类名:必选参数,用于指定类的名称,类名必须是合法的Java标识符。一般情况下,要求首字母大写。extends 父类名:可选参数,用于指定要定义的类继承于哪个父类。当使用extends关键字时,父类名为必选参数。implements 接口列表:可选参数,用于指定该类实现的是哪些接口。当使用implements关键字时,接口列表为必选参数。当接口列表中存在多个接口名时,各个接口名之间使用逗号分隔。
//用implements实现多个接口 class Phone implements USB,WIFI,GPRS{ //用复写实现接口USB的抽象方法 public void usbread(){ System.out.println("USB Phoen read"); } public void usbwrite(){ System.out.println("USB Phone write"); } //继承了WIFI的抽象方法 open() close(),必须复写实现他们 public void wifiopen(){ System.out.println("WIIF open"); } public void wificlose(){ System.out.println("WIFI close"); } //3G模块实现 public void gprs_open(){ System.out.println("GPRS open"); } public void gprs_close(){ System.out.println("GPRS close"); } }
继承接口
在类的继承中,只能做单重继承,而实现接口时,一次则可以实现多个接口,每个接口间使用逗号“,”分隔。//用PhoneFunction 继承wifi和usb接口 //用extends 继承,不是用implements interface PhoneFunction extends WIFI,GPRS,USB{ //继承了多个接口,也可以在这个增加方法 }
接口中方法名冲突
如果出现方法冲突时,则只要实现一个方法就可以了。
interface GPRS{ //在WIFI中定义一样的方法声明,然后在同一个类实现回出现什么? public void open(); public void close(); }
//wifi接口的创建 interface WIFI{ //在GPRS中定义一样的方法,然后在实现中怎么办? public void open(); public void close(); }
//用implements实现多个接口 class Phone implements USB,WIFI,GPRS{ //用复写实现接口USB的抽象方法 public void usbread(){ System.out.println("USB Phoen read"); } public void usbwrite(){ System.out.println("USB Phone write"); } //继承两个接口中的相同方法声明 public void open(){ System.out.println("WIF GPRS open"); } public void close(){ System.out.println("WIFI GPRS close"); } }
public class Test{ public static void main(String[] args){ //1.用Phone实现多个接口(接口WIFI,USB) Phone iphone=new Phone(); //通过向上转型 WIFI wifi=iphone; wifi.open(); wifi.close(); GPRS gprs=iphone; gprs.open(); gprs.close(); /*输出: WIF GPRS open WIFI GPRS close WIF GPRS open WIFI GPRS close *///同一个方法实现,无论怎么调用都是统一个方法 } }
接口中常量冲突
如果出现常量或方法名冲突的情况,解决该问题时,如果常量冲突,则需要明确指定常量的接口,这可以通过“接口名.常量”实现。
package me.confict; interface GPRS{ //我们定义名字为ersion的常量 //定义可以不写 public static final,因为默认会自动添加 public static final double VERSION=4.03; public void justtest(); } //wifi接口的创建 interface WIFI{ //我们定义相同的常量 public static final double VERSION=2.3; public void say(); } //然后我们通过一个class把两个接口实现了 class TestConflict implements GPRS,WIFI{ public void say(){ System.out.println("这是用于测试冲突的常量"); } public void justtest(){ //请问这应该输出哪个接口的VERSION? //咱先编译试试 // System.out.println("VERSION= "+VERSION); /*然后编译出错: yg@Gander:~/Desktop/code$ javac -d . TestConflict.java TestConflict.java:32: error: reference to VERSION is ambiguous, both variable VERSION in GPRS and variable VERSION in WIFI match System.out.println("VERSION= "+VERSION); ^ 1 error *///reference to VERSION is ambiguous,编译器指出在编译时候,引用不明确,模糊不清,存在歧意。 //咱修改方法,然后用指明的指出这个常量属于哪一个接口 System.out.println("WIFI.VERSION= "+WIFI.VERSION); System.out.println("GPRS.VERSION= "+GPRS.VERSION); } //完了当然要用main()测试咯 public static void main(String[] args){ TestConflict coco=new TestConflict(); coco.justtest(); //编译无错,运行 /*输出: yg@Gander:~/Desktop/code$ java me.confict.TestConflict WIFI.VERSION= 2.3 GPRS.VERSION= 4.03 *///这回是不是可以了输出咱想要的变量 } }
作者:YangGan