上次我们讲了一下抽象类(java面向对象(五)——抽象类)这次我们讲和抽象类密切相关的接口。
接口
接口相当于一个极端抽象类,接口内不可以包含普通方法,只能含有抽象方法。java8对接口进行了一定改进允许在接口内定义默认方法,默认方法可以提供方法实现。(默认方法也只能在接口中使用)
接口定义:使用interface关键字,基本语法为
//当接口继承自接口使用extends,类继承自接口使用implements
[修饰符] interface 接口名 extends 父接口{
常量定义;
抽象方法定义;
内部类,接口,枚举定义;
默认方法或类方法定义;
}
接口内的方法只能是抽象方法,类方法,默认方法。普通方法不管是使用public abstract修饰符都默认使用public abstract修饰。普通方法不可以有方法体,但是类方法和默认方法都必须要有方法实现。
接口作用
接口不可用于创建实例但是可以用来声明引用类型变量。这个引用类型变量必须要引用到其实现类的对象。接口的主要用途就是被实现类实现
1)定义变量,也可以用于强制类型转换
2)调用接口中定义的常量
3)被其它类实现
实现接口和继承父类相似,可以获得接口中定义的常量,方法,当一个类既要继承父类又要实现多个接口那么implements部分需要放在extends部分之后。类实现一个或者多个接口之后,这个类需要完全实现这些接口中定义所有的抽象方法。
//定义一个接口
interface Product{
int getProduceTime();
}
//使用ProduceImpl类实现接口
public class ProduceImpl implements Produce{
private String[] printData=new String[20];
private int dataNum=0;
public void out(){
while(dataNum>0){
System.out.println("打印机打印"+printData[0]);
//将作业队列整体前移并且将剩下的作业数-1
System.arraycopy(printData,1,printData,0,--dataNum);
}
}
public void getData(String msg){
if(dataNum>=20){
System.out.println("输出队列已满,添加失败");
}else{
//将打印数据添加到队列里,已经保存的数量+1
printData[dataNum++]=msg;
}
}
//重写接口中的方法
public int getProduceTime(){
return 45;
}
public static void main(String[] args){
//创建一个ProduceImpl对象当成Produce类
Produce p =new ProduceImpl();
System.out.println(p.getProduceTime());
//直接创建子类
ProduceImpl p1=new ProduceImpl();
p1.getData("学习java");
p1.getData("java是最好的语言");
p1.out();
}
}
抽象类和接口
相似性:
1)接口和抽象类都不可以被实例化,位于继承树的顶端
2)接口和抽象类都可以包含抽象方法,子类必须实现这些抽象方法
差别:
1)接口是系统和外界交互的窗口,体现一种规范。定义了实现者需要提供的方法(使用方法形式来提供),定义了使用者可以调用的服务,相当于系统的总纲。抽象类是多个子类的共同父类,体现的模板设计。相当于系统的中间产品。
2)接口中含有抽象方法和默认方法丹斯不可为普通方法提供方法实现,抽象类可以包含普通方法
3)接口只可以定义静态常量不可定义普通常量
4)接口不含构造器,抽象可以包含构造器,但是只能在子类纪念高兴抽象类的初始化
5)接口不含初始化块,抽象可含初始化块
6)一个类只有一个直接弗雷但是可以有多个接口
Lambda表达式
这个是java8的重要更新,支持将代码块作为方法参数,使用更简洁的代码进行创建只有一个抽象方法的接口(这种接口被称为函数式接口)的实例
Lambda运算符:所有Lambda表达式都是用的新的运算符"=>"称为转到,运算符左边指定输入参数,右边是lanbda函数主体
//一个参数时
param->expr
//多个参数
(param-list)->expr
Lambda表达式是一个匿名函数,可以理解为是一段可以传递的代码块,完全可以简化匿名内部类
例如 使用匿名内部类
接口 Command
public interface Command{
void process(int[] array);
}
类 ProcessArray
public ProcessArray{
public void process(int[] array,Command c){
c.process(int[] array);
}
}
ProcessArray类的process方法需要借助Command接口来对数组array进行操作。这种需求来源于需要对数组进行不同的操作,可以使用Command接口的不同实现类来完成。这种设计方式成为命令模式。
Test类
public class Test{
public static void mian(String[] args){
ProcessArray pa = new ProcessArray();
int[] target = {1,2,3,4};
pa.process(target ,new Command(){
publiv void process(int[] target){
int sum=0;
for(int tmp:target){
sum+=tmp;
}
System.out.println("数组之和为"+sum);
}
});
}
}
使用Lambda简化匿名内部类对象
public clss Test{
public satic void main(String[] args){
ProcessArray pa = new ProcessArray();
int[] target = {1,2,3,4};
pa.process(target, (int[] array) ->{
int sum=0;
for(int tmp:taget){
sum+=tage;
System.out.println("数组之和为"+sum);
});
}
}
形参列表:允许省略形参类型,如果只有一个参数可以省略括号
箭头(->)转到符号
代码块:如果代码块只有一条语句可以省略花括号。如果只有return语句可以省略return关键字,Lambda的代码块仅有一条省略的returnn语句,因此会自动返回这条语句的值