一、接口
接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,在根据具体情况把这些方法写出来。
-
定义
interface 接口名{
//属性
//方法
}
小结:
1.在JDK7.0前接口里的所有方法都没有方法体,即都是抽象方法。
2.JDK8.0后接口可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现
3.JDK9.0后允许有私有方法 -
接口中的方法包括
抽象方法:访问权限一定为public;abstract,public修饰符可省略;
实例方法:定义实例方法需要用default关键字修饰,置于public之后,数据类型之前;访问权限一定为public,public修饰符可省略;
static方法
private方法:配合default实例方法,实现方法的复用。 -
接口中的属性:只能是final的,而且是public static final修饰符。比如:int a=1;实际上是 public static final int a=1;(必须初始化)
二、实现接口
- 类实现接口
Java中接口由类来实现,以便使用接口中的方法
class 类名 implements 接口{
自己属性;
自己方法;
必须实现的接口的抽象方法
} - 注意事项
1)重写接口中的方法时要去掉实例方法的default,并且public不可省略
2)如果父类实现了某个接口, 子类自然也实现了该接口,子类不必再显式地用implement声明实现了这个结构。
3)java提供的接口都在相应的包里,通过import语句不仅可以引入包中的类,也可以引入包中的接口。
4)接口不能被实例化,只能引用
5)一个普通类实现接口,就必须将该接口的所有方法都实现。
6)抽象类实现接口,可以不用实现接口的方法。
7)一个类同时可以实现多个接口
8)接口中属性的访问形式:接口名.属性名
9)一个接口不能继承其它的类,但是可以继承多个别的接口,如:interface A extends B,C{}
10)接口的修饰符只能是public和默认,这点和类的修饰符是一样的。
三、实现接口vs继承类
-
接口和继承解决的问题不同
继承的价值主要在于:解决代码的复用性和可维护性。
接口的价值主要在于:设计,设计好各种规范(方法),让其它类去实现这些方法。
-
接口比继承更加灵活
接口比继承更加灵活,继承是满足is - a的关系,而接口只需满足 like - a的关系
-
接口在一定程度上实现代码解耦[即:接口规范性+动态绑定机制]
四、接口回调
1.用接口声明的变量就叫做接口变量
2.接口属于引用型变量,在接口变量中可以存放实现该接口的类的实例的引用,即存放对象的引用。
3.接口回调是指可以把实现某一接口的类创建的对象的引用赋值给该接口声明的接口变量,那么该接口变量就可以调用被类实现的接口方法以及接口提供的default方法或类重写的default方法。实际上当接口变量调用被类实现的接口方法时就是通知相应的对象调用这个方法。
4.接口无法调用接口中其他的非接口方法
interface ShowMessage {
void 显示商标(String s);
default void outPutStart(){
System.out.println("********");
}
}
class TV implements ShowMessage {
public void 显示商标(String s) {
System.out.println("tvtvtvtv");
System.out.println(s);
System.out.println("tvtvtvtv");
}
}
class PC implements ShowMessage {
public void 显示商标(String s) {
System.out.println("pcpcpcpc");
System.out.println(s);
System.out.println("pcpcpcpc");
}
}
public class Example6_2 {
public static void main(String args[]) {
ShowMessage sm; //声明接口变量
sm=new TV(); //接口变量中存放对象的对象
sm.显示商标("长城牌电视机"); //接口回调
sm=new PC(); //接口变量中存放对象的对象
sm.outPutStart();
sm.显示商标("华为个人电脑"); //接口回调
sm.outPutStart();
}
}
五、函数接口与Lambda表达式
1.函数接口
如果一个接口中有且只有一个抽象方法,称这样的方法为单接口。
从JDK8开始java使用Lambda表达式,并且将单接口称为函数接口。
2.Lambda表达式
Lambda表达式:只写参数列表和方法体的匿名方法(参数列表和方法体之间的符号是->)
(参数列表)->{
方法体
}
ps:Lambda表达式由于太过简化,需要有特殊上下文才能使用。因此主要将其运用于单接口
3.接口回调Lambda表达式实现的接口方法
直接将Lambda表达式的值赋给接口变量即可,可以使代码更加简洁。
六、理解函数
-
理解的关键点
(1)接口可以抽象出重要的行为标准,该行为标准用抽象方法来表示。
(2)可以把实现接口的类的对象的引用赋值给接口变量,该接口变量可以调用被该类实现的接口方法,即体现该类根据接口中的行为标准给出的具体行为。 -
接口的思想在于它可以要求某些类有相同名称的方法,但方法的具体内容(方法体的内容)可以不同,即要求这些类实现接口,以保证这些类一定有接口中所声明的方法(即所谓的方法绑定)。接口在要求一些类有相同名称的方法的同时并不强迫这些类具有相同的父类。
七、接口与多态
由接口产生的多态是指不同的类在实现同一个接口时可能具有不同的实现方式,那么接口变量在回调接口方法时就可能具有多种形态。
interface CompurerAverage {
public double average(double a,double b);
}
class A implements CompurerAverage {
public double average(double a,double b) {
double aver=0;
aver=(a+b)/2;
return aver;
}
}
class B implements CompurerAverage {
public double average(double a,double b) {
double aver=0;
aver=Math.sqrt(a*b);
return aver;
}
}
public class Example6_5 {
public static void main(String args[]) {
CompurerAverage computer;
double a=11.23,b=22.78;
computer = new A();
double result = computer.average(a,b);
System.out.printf("%5.2f和%5.2f的算术平均值:%5.2f\n",a,b,result);
computer = new B();
result= computer.average(a,b);
System.out.printf("%5.2f和%5.2f的几何平均值:%5.2f",a,b,result);
}
}
八、接口参数
如果一个方法的参数是接口类型,就可以将任何实现该接口的类的实例的引用传递给该接口参数,那么接口参数就可以回调类实现的接口方法。如果参数是函数接口,也可以将Lambda表达式的值传递给该接口参数,那么接口参数就可以调用Lambda表达式实现的接口方法。
interface SpeakHello {
void speakHello();
}
class Chinese implements SpeakHello {
public void speakHello() {
System.out.println("中国人习惯问候语:你好,吃饭了吗? ");
}
}
class English implements SpeakHello {
public void speakHello() {
System.out.println("英国人习惯问候语:你好,天气不错 ");
}
}
class KindHello {
public void lookHello(SpeakHello hello) { //接口类型参数
hello.speakHello(); //接口回调
}
}
public class Example6_6 {
public static void main(String args[]) {
KindHello a = new KindHello();
Chinese ccc = new Chinese();
a.lookHello(ccc );
a.lookHello(new English());
a.lookHello( ()->{
System.out.println("码农习惯问候语:no bug");} );//向参数传递Lambda表达式的值
}
}
九、抽象类和接口的比较
abstract类和接口的比较如下:
1)abstract类和接口都有abstract方法
2)接口中只可以有常量,不能有变量;而abstract类中既可以有常量也可以有变量
3)abstract类中也可以有非abstract方法,接口可以有abstract方法、default实例方法,不可以有非default的实例方法
十、面向接口编程
面向接口编程,是指当设计某个重要的类时不让该类面向具体的类,而是面向接口即所设计类中的重要数据是接口声明的变量,而不是具体类声明的对象。
使用接口进行程序设计的核心思想是使用接口回调,即接口变量存放实现该接口的类的对象的引用,从而接口变量就可以回调类实现的接口方法。利用接口也可以体现程序设计的“开-闭原则”,即对扩展开放,对修改关闭。
当然,在程序设计好之后,首先应该把对接口的修改“关闭”,否则一旦修改接口,例如为它再增加一个abstract方法,那么实现该接口的类都需要做出修改。但是,在程序设计好之后,应该把对增加实现接口的类“开放”,即在程序中再增加实现接口的类时不需要修改其他重要的类。