第十二课 《Java的接口》
第一部分:不知道的内容百度百科:
@1接口的定义:
Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
两种含义:一,Java接口,Java语言中存在的结构,有特定的语法和结构;二,一个类所具有的方法的特征集合,是一种逻辑上的抽象。前者叫做“Java接口”,后者叫做“接口”。
@2接口的功能:
在Java语言规范中,一个方法的特征仅包括方法的名字、参数的数目和类型,而不包括方法的返回类型、参数名以及所抛出来的异常。在Java编译器检查方法的重载时,会根据这些条件判断两个方法是否是重载方法。但在Java编译器检查方法的置换时,则会进一步检查两个方法(分处超类型和子类型)的返还类型和抛出的异常是否相同。
接口实现和类继承的规则不同,为了数据的安全,继承时一个类只有一个直接父类,也就是单继承,但是一个类可以实现多个接口,接口弥补了类的不能多继承缺点,继承和接口的双重设计既保持了类的数据安全也变相实现了多继承。
Java接口本身没有任何实现,因为Java接口不涉及表象,而只描述public行为,所以Java接口比Java抽象类更抽象化。但是接口不是类,不能使用new 运算符实例化一个接口。如 x=new comparable(......);//这个是错误来的。但是可以声明接口变量Comparable x; //这是允许的。
Java接口的方法只能是抽象的和公开的,Java接口不能有构造器,Java接口可以有public、static和final属性。即接口中的属性可以定义为 public static final int value=5; [1]
接口把方法的特征和方法的实现分割开来。这种分割体现在接口常常代表一个角色,它包装与该角色相关的操作和属性,而实现这个接口的类便是扮演这个角色的演员。一个角色由不同的演员来演,而不同的演员之间除了扮演一个共同的角色之外,并不要求其它的共同之处。
@3接口的使用:
两个类中的两个类似的功能,调用他们的类动态的决定一种实现,那他们提供一个抽象父类,子类分别实现父类所定义的方法。
问题的出现:Java是一种单继承的语言,一般情况下,哪个具体类可能已经有了一个超类,解决是给它的父类加父类,或者给它父类的父类加父类,直到移动到类等级结构的最顶端。这样一来,对一个具体类的可插入性的设计,就变成了对整个等级结构中所有类的修改。
可插入性
在一个等级结构中的任何一个类都可以实现一个接口,这个接口会影响到此类的所有子类,但不会影响到此类的任何超类。此类将不得不实现这个接口所规定的方法,而其子类可以从此类自动继承这些方法,当然也可以选择置换掉所有的这些方法,或者其中的某一些方法,这时候,这些子类具有了可插入性(并且可以用这个接口类型装载,传递实现了他的所有子类)。
我们关心的不是那一个具体的类,而是这个类是否实现了我们需要的接口。
接口提供了关联以及方法调用上的可插入性,软件系统的规模越大,生命周期越长,接口使得软件系统的灵活性和可扩展性,可插入性方面得到保证。
类型
使用Java接口将软件单位与内部和外部耦合起来。使用Java接口不是具体的类进行变量的类型声明,方法的返还类型声明,参量的类型声明,以及数据类型的转换。
在理想的情况下,一个具体的Java类应当只实现Java接口和抽象Java类中声明的方法,而不应当给多余方法。
等级结构
Java接口(以及抽象类)一般用来作为一个类型的等级结构的起点。
如果一个类已经有了一个主要的超类型,那么通过实现一个接口,这个类可以拥有另一个次要的超类型,这种次要的超类型叫做混合类型。
六个测试Demo来讲讲什么是接口,接口如何定义的:
案例一
一、基本概念
接口(Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合。接口通常以interface来声明。
一个类通过继承接口的方式,从而来继承接口的抽象方法。
如果一个类只由抽象方法和全局常量组成,那么这种情况下不会将其定义为一个抽象类。只会定义为一个接口,
所以接口严格的来讲属于一个特殊的类,而这个类里面只有抽象方法和全局常量,就连构造方法也没有。
由于接口里面存在抽象方法,所以接口对象不能直接使用关键字new进行实例化。接口的使用原则如下:
(1)接口必须要有子类,但此时一个子类可以使用implements关键字实现多个接口;
(2)接口的子类(如果不是抽象类),那么必须要覆写接口中的全部抽象方法;
(3)接口的对象可以利用子类对象的向上转型进行实例化。
package com.JavaBasicsDemo7.Interface1; /** * 由于接口里面存在抽象方法,所以接口对象不能直接使用关键字new进行实例化。接口的使用原则如下: * (1)接口必须要有子类,但此时一个子类可以使用implements关键字实现多个接口; * (2)接口的子类(如果不是抽象类),那么必须要覆写接口中的全部抽象方法; * (3)接口的对象可以利用子类对象的向上转型进行实例化。 */ public interface A { public static final String MSG = "hello";//全局常量 public abstract void print();//抽象方法 } package com.JavaBasicsDemo7.Interface1; public interface B { public abstract void get(); } package com.JavaBasicsDemo7.Interface1; public interface C { public abstract void set(); } package com.JavaBasicsDemo7.Interface1; public interface D { public abstract void getString(); } package com.JavaBasicsDemo7.Interface1; public class TestDemo { public static void main(String[] args) { Test test = new Test();//实例化子类对象 A a = test;//向上转型 B b = test;//向上转型 C c=test; D d=test; a.print(); b.get(); c.set(); d.getString(); } }
package com.JavaBasicsDemo7.Interface1; /** * 我们发现,从定义结构来讲,A和B两个接口没有任何直接联系,但这两个接口却拥有同一个子类。我们不要被类型和名称所迷惑, * 因为实例化的是X子类,而这个类对象属于B类的对象,所以以上代码可行,只不过从代码的编写规范来讲,并不是很好。 */ //class 子类 [extends 父类] [implemetns 接口1,接口2,...] {} public class TestDemo1 { public static void main(String[] args) { A a = new Test(); B b = (B) a; b.get(); System.out.println(a instanceof A); System.out.println(a instanceof B); } }
我们发现,从定义结构来讲,A和B两个接口没有任何直接联系,但这两个接口却拥有同一个子类。我们不要被类型和名称所迷惑,
* 因为实例化的是X子类,而这个类对象属于B类的对象,所以以上代码可行,只不过从代码的编写规范来讲,并不是很好。
案例二:
对于接口,里面的组成只有抽象方法和全局常量,所以很多时候为了书写简单,
* 可以不用写public abstract 或者public static final。并且,接口中的访问权限只有一种:public
* ,即:定义接口方法和全局常量的时候就算没有写上public,那么最终的访问权限也是public,注意不是default。以下两种写法是完全等价的:
package com.JavaBasicsDemo7.Interface2; public interface A { public static final String MSG = "hello";//全局常量 public abstract void print();//抽象方法 } package com.JavaBasicsDemo7.Interface2; public interface B { public abstract void get(); } package com.JavaBasicsDemo7.Interface2; abstract class C{//定义一个抽象类C public abstract void change(); } package com.JavaBasicsDemo7.Interface2; /** * 对于接口,里面的组成只有抽象方法和全局常量,所以很多时候为了书写简单, * 可以不用写public abstract 或者public static final。并且,接口中的访问权限只有一种:public * ,即:定义接口方法和全局常量的时候就算没有写上public,那么最终的访问权限也是public,注意不是default。以下两种写法是完全等价的: * * interface A{ * public static final String MSG = "hello"; * public abstract void print(); * } * 等价 * interface A{ * String MSG = "hello"; * void print(); * } * 是,这样会不会带来什么问题呢?如果子类子类中的覆写方法也不是public,我们来看: */ class X extends C implements A,B{//X类继承C类,并实现了A和B两个接口 @Override public void print() { System.out.println("接口A的抽象方法print()"); } @Override public void get() { System.out.println("接口B的抽象方法get()"); } @Override public void change() { System.out.println("抽象类C的抽象方法change()"); } }
案例三:
/这是因为接口中默认是public修饰,若子类中没用public修饰,则访问权限变严格了,给子类分配的是更低的访问权限。所以,在定义接口的时候强烈建议在抽象方法前加上public ,子类也加上:
package com.JavaBasicsDemo7.a; interface A{ String MSG = "hello"; void print(); } class X implements A{ //这是因为接口中默认是public修饰,若子类中没用public修饰,则访问权限变严格了,给子类分配的是更低的访问权限。所以,在定义接口的时候强烈建议在抽象方法前加上public ,子类也加上: void print() { System.out.println("接口A的抽象方法print()"); } } class TestDemo { public static void main(String[] args){ A a = new X(); a.print(); } }
package com.JavaBasicsDemo7.a; interface A{ String MSG = "hello"; void print(); } class X implements A{ //这是因为接口中默认是public修饰,若子类中没用public修饰,则访问权限变严格了,给子类分配的是更低的访问权限。所以,在定义接口的时候强烈建议在抽象方法前加上public ,子类也加上: public void print() { System.out.println("接口A的抽象方法print()"); } } class TestDemo { public static void main(String[] args){ A a = new X(); a.print(); } }
案例四:
由此可见,从继承关系来说接口的限制比抽象类少:
(1)一个抽象类只能继承一个抽象父类,而接口可以继承多个接口;
(2)一个子类只能继承一个抽象类,却可以实现多个接口(在Java中,接口的主要功能是解决单继承局限问题)
package com.JavaBasicsDemo7.b; /** * 由此可见,从继承关系来说接口的限制比抽象类少: * (1)一个抽象类只能继承一个抽象父类,而接口可以继承多个接口; * (2)一个子类只能继承一个抽象类,却可以实现多个接口(在Java中,接口的主要功能是解决单继承局限问题) */ interface A{ public void funA(); } interface B{ public void funB(); } //C接口同时继承了A和B两个接口 interface C extends A,B{//使用的是extends public void funC(); } class X implements C{ @Override public void funA() { } @Override public void funB() { } @Override public void funC() { } }
案例五:
从接口的概念上来讲,接口只能由抽象方法和全局常量组成,但是内部结构是不受概念限制的,
正如抽象类中可以定义抽象内部类一样,在接口中也可以定义普通内部类、抽象内部类和内部接口(但从实际的开发来讲,
用户自己去定义内部抽象类或内部接口的时候是比较少见的),范例如下,在接口中定义一个抽象内部类:
package com.JavaBasicsDemo7.c; /** * interface A{ * public void funA(); * * static interface B{//使用了static,是一个外部接口 * public void funB(); * } * } * class X implements A.B{ * * @Override * public void funB() { * * } * * } */ /** * 从接口的概念上来讲,接口只能由抽象方法和全局常量组成,但是内部结构是不受概念限制的, * 正如抽象类中可以定义抽象内部类一样,在接口中也可以定义普通内部类、抽象内部类和内部接口(但从实际的开发来讲, * 用户自己去定义内部抽象类或内部接口的时候是比较少见的),范例如下,在接口中定义一个抽象内部类: */ interface A { public void funA(); abstract class B {//定义一个抽象内部类 public abstract void funB(); } }
案例六:经典案例:仔细去想象:去理解接口的作用:
package com.JavaBasicsDemo7.Interface; public interface USBA { public void turnOn(); //设备启动' public void turnruning(); //设备运行 public void turnOff(); //设备关闭 public void name(); //设备名称 public void color(); //设备颜色 public void height();//设备高度 public void weight();//设备宽度 public void length(); //设备长度 }
package com.JavaBasicsDemo7.Interface; public class ElectronicWhiteboard implements USBA{ @Override public void turnOn() { // TODO Auto-generated method stub System.out.println("电子白板真在运行,打开你要的软件,并开始运行"); } @Override public void turnruning() { // TODO Auto-generated method stub System.out.println("电子白板真在运行,正在运行这个程序,并开始运行"); } @Override public void turnOff() { // TODO Auto-generated method stub System.out.println("电子白板结束自己运行的程序系统"); } @Override public void name() { // TODO Auto-generated method stub System.out.println("电子白板名称为huaweiwww"); } @Override public void color() { // TODO Auto-generated method stub System.out.println("电子白板色彩为back"); } @Override public void height() { // TODO Auto-generated method stub System.out.println("电子白板高度为150cm"); } @Override public void weight() { // TODO Auto-generated method stub System.out.println("电子白板宽度为200cm"); } @Override public void length() { // TODO Auto-generated method stub System.out.println("电子白板长度为300cm"); } } package com.JavaBasicsDemo7.Interface; public class Keyboarda implements USBA { @Override public void turnOn() { // TODO Auto-generated method stub System.out.println("键盘已启动,请开始以下程序"); } @Override public void turnruning() { // TODO Auto-generated method stub System.out.println("键盘开始运行自己设定的程序"); } @Override public void turnOff() { // TODO Auto-generated method stub System.out.println("键盘结束自己运行的程序系统"); } @Override public void name() { // TODO Auto-generated method stub System.out.println("键盘名称为huaweiwww"); } @Override public void color() { // TODO Auto-generated method stub System.out.println("键盘色彩为back"); } @Override public void height() { // TODO Auto-generated method stub System.out.println("键盘高度为10cm"); } @Override public void weight() { // TODO Auto-generated method stub System.out.println("键盘宽度为30cm"); } @Override public void length() { // TODO Auto-generated method stub System.out.println("键盘长度为80cm"); } } package com.JavaBasicsDemo7.Interface; public class Mousea implements USBA { @Override public void turnOn() { // TODO Auto-generated method stub System.out.println("鼠标已启动,请开始以下程序"); } @Override public void turnruning() { // TODO Auto-generated method stub System.out.println("鼠标开始运行自己设定的程序"); } @Override public void turnOff() { // TODO Auto-generated method stub System.out.println("鼠标结束自己运行的程序系统"); } @Override public void name() { // TODO Auto-generated method stub System.out.println("鼠标名称为huaweiwwwe"); } @Override public void color() { // TODO Auto-generated method stub System.out.println("鼠标色彩为back"); } @Override public void height() { // TODO Auto-generated method stub System.out.println("鼠标高度为50mm"); } @Override public void weight() { // TODO Auto-generated method stub System.out.println("鼠标宽度为500mm"); } @Override public void length() { // TODO Auto-generated method stub System.out.println("鼠标长度为900mm"); } } package com.JavaBasicsDemo7.Interface; public class Phonea implements USBA{ @Override public void turnOn() { // TODO Auto-generated method stub System.out.println("手机已启动,请开始以下程序"); } @Override public void turnruning() { // TODO Auto-generated method stub System.out.println("手机开始运行自己设定的程序"); } @Override public void turnOff() { // TODO Auto-generated method stub System.out.println("手机结束自己运行的程序系统"); } @Override public void name() { // TODO Auto-generated method stub System.out.println("手机名称为huaweiwww"); } @Override public void color() { // TODO Auto-generated method stub System.out.println("手机色彩为back"); } @Override public void height() { // TODO Auto-generated method stub System.out.println("手机高度为8cm"); } @Override public void weight() { // TODO Auto-generated method stub System.out.println("手机宽度为15cm"); } @Override public void length() { // TODO Auto-generated method stub System.out.println("手机长度为20cm"); } } package com.JavaBasicsDemo7.Interface; public class telephone implements USBA { @Override public void turnOn() { // System.out.println("电话已启动,请打电话"); } @Override public void turnruning() { // TODO Auto-generated method stub System.out.println("电话开始进行联系对方"); } @Override public void turnOff() { // TODO Auto-generated method stub System.out.println("电话结束:请把电源turnoff"); } @Override public void name() { // TODO Auto-generated method stub System.out.println("电话名称为大哥大"); } @Override public void color() { // TODO Auto-generated method stub System.out.println("电话色彩为开门红"); } @Override public void height() { // TODO Auto-generated method stub System.out.println("电话高度为6cm"); } @Override public void weight() { // TODO Auto-generated method stub System.out.println("电话宽度为12cm"); } @Override public void length() { // TODO Auto-generated method stub System.out.println("电话长度为18cm"); } }
package com.JavaBasicsDemo7.Interface; import java.util.ArrayList; public class DwmoTesta { public static void main(String[] args) { ArrayList<USBA> usbs =new <USBA> ArrayList (); usbs.add( new Mousea()); //类 usbs.add(new Keyboarda()); usbs.add(new Phonea()); usbs.add(new ElectronicWhiteboard ()); usbs.add(new telephone ()); System.out.println("用for循化输出内容"); for (int i = 0; i < usbs.size(); i++) { usbs.get(i).height(); } for (int i = 0; i < usbs.size(); i++) { usbs.get(i).weight(); } for (int i = 0; i < usbs.size(); i++) { usbs.get(i).length(); } System.out.println("设定设备的长:宽:高"); for (int i = 0; i < usbs.size(); i++) { usbs.get(i).turnOn(); //接口方法 } System.out.println("设定程序启动的系统"); System.out.println("============================"); for (int i = 0; i < usbs.size(); i++) { usbs.get(i).turnOff(); } System.out.println("设置程序正在运行的程序"); System.out.println("============================"); for (int i = 0; i < usbs.size(); i++) { usbs.get(i).turnruning(); } System.out.println("设置程序名称"); System.out.println("**********************"); for (int i = 0; i < usbs.size(); i++) { usbs.get(i).name(); } System.out.println("设置设备色彩为"); System.out.println("**********************"); for (int i = 0; i < usbs.size(); i++) { usbs.get(i).color(); } } }
看懂了第六个案例说明自己对接口的定义有礼一点的了解。