1、接口
接口的好处:(接口的作用是将所有对象(实现类)共同的部分放置在一起,减少重复定义)
通用性(无差别对待)
隔离性(隔离无关功能)
基本定义格式:
public interface 接口名称{
语句块:组成部分:抽象方法、常量、默认方法(java8)、静态方法(java8)、私有方法(java9)
}
<1>抽象方法定义(LittleBaby)
抽象方法对实现类有一定的约束力,但不是完全约束,对于不同实现类在同一约束下的行为只要符合抽象方法的统一约束即可。
public abstract 返回值类型 方法名称(参数类型 参数名称);
注意事项:(1)接口中的抽象方法,修饰如果写必须是public abstract
(2)接口中的抽象方法,修饰符可以省略不写,默认就是:public abstract
(3)接口中的抽象方法只有方法头,没有方法体(即{}及其中的内容)
package xwg.Eric.study.port;
public interface LittleBaby {
public abstract String xue();
public abstract String xiao();
public abstract String lei();
}
<2>接口实现类的定义(LittleBaby)(为接口类定义方法体,实现功能)
如果要使用定的义好接口,必须有一个接口的“实现类”。
定义实现类格式为:
public class 实现类名称 implements 接口名称 {
//覆盖重写所有的抽象方法
/*覆盖重写(Override)的步骤:
*(1)将接口当中的抽象方法复制粘贴
*(2)去掉abstract关键字
*(3)写上大括号方法体
*/
}
package xwg.Eric.study.port;
public class LittelBabyImpl implements LittleBaby {
public String xue() {
System.out.println("小宝贝");
return null;
}
public String xiao() {
return null;
}
public String lei() {
return null;
}
public void play() {
}
}
<3>接口与实现类的基本使用(UseBaby)
使用方法:(1)创建:接口名称 引用名 = new 实现类名称();
(2)调用:引用名.抽象方法名(参数)
注意事项:(1)左边是接口口类型,只能调用接中定义的抽象方法,不能调用右侧实现类当中特有的方法(接口隔离)
(2)当调用接口当中的抽象方法时,真正进行运行的是右侧new的时候类的具体方法内容。
(3)调用的时候看左边,运行的时候看右边。LittleBaby baby = new LittelBabyImpl();
package xwg.Eric.study.port;
public class UseBaby {
public static void main(String[] args) {
LittleBaby baby = new LittelBabyImpl();
baby.xue();
baby.xiao();
baby.lei();
baby.play();//不能调用接口中没有定义的抽象方法
}
}
2、面向接口的编程
使用接口作为左侧类型的优点:屏蔽右侧的个性特有内容,达到隔离、统一的目的
面向接口编程:如果使用功能,接口就已经可以满足,不在乎具体的类是谁,只在乎接口即可
3、λ(Lambda)表达式(函数式编程)
一般建议使用接口名后加(大写i)Impl作为实现类
package xwg.Eric.study.port;
public interface CalculaterIterface {
public abstract double add(double a, double b);
}
package xwg.Eric.study.port;
import java.util.Scanner;
public class UseCalculaterInterface {
public static void main(String[] args) {
method((a, b) -> a + b);//λ表达式
}
public static void method(CalculaterIterface cal) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入a:");
double a = sc.nextFloat();
System.out.print("请输入b:");
double b = sc.nextFloat();
double result = cal.add(a, b);
System.out.print("结 果:" + result);
sc.close();
}
}
λ表达式:method((a,b) -> a + b)
method方法需要一个Calculater接口类型的参数,λ表达式就是充当Calculater接口类型的参数;
λ前面的小括号就是接口抽象方法的小括号,箭头代表拿着小括号的动作做什么事情,是一个指向动作,箭头后面表示拿到参数后执行的操作是什么。
lambda表达式的语义本身就代表需要执行的操作是什么,没有对象的概念在里面,更加简单直观。
<1>λ表达式标准格式
使用条件:需要存在函数式的推断环境
检查方法:(1)通过方法的参数类型来确定那个是函数式接口(2)通过赋值来确定那个是函数式接口
标准格式:抽象方法:public abstract int sum (int a , int b);
lambda的标准格式:(int a ,int b) -> { return a + b; }
lambda表达式的返回值类型要与定义接口的返回值类型相同
<2>λ表达式简便格式
在lambda表达式中凡是可以推导的都可以省略
(1)表达式中的参数类型可以省略不写
(2)如果参数只有一个,那么小括号可以省略
(3)如果语句只有一个,大括号和return也可以省略
package xwg.Eric.study.port;
import java.util.Scanner;
public class UseCalculaterInterface {
public static void main(String[] args) {
method((double a, double b) -> { return a + b;} );
method((a, b) -> a + b);//最简格式
}
public static void method(CalculaterIterface cal) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入a:");
double a = sc.nextFloat();
System.out.print("请输入b:");
double b = sc.nextFloat();
double result = cal.add(a, b);
System.out.print("结 果:" + result);
sc.close();
}
}
<3>Lambda的上下文推断
(1)调用方法的时候,参数类型是函数式接口类型,所以Lambda可以推断出是哪个接口
(2)根据赋值语句的左侧的类型来进行Lambda上下文推断
Lambda表达式不能直接写,需要有赋值语句,因为没有上下文环境,其无法推断是哪个函数式接口。
4、函数式接口
java当中使用Lambda表达式的前提是:必须有函数式接口
函数式接口:在定义接口中有且仅有一个抽象方法的接口。叫做函数式接口
检测接口是不是函数式接口只需要在public interface前面加:@FunctionalIterface 即可
5、简化λ表达式
对于λ表达式实现的功能,如果在某个类中已经定义,则会造成冗余的现象,我们可以使用如下来简化
格式:类名称::方法名称 //可实现与λ表达式相同的功能。