java从jdk8开始提供了lambda表达式。
lambda表达式意在简化函数式接口。
何为函数式接口?原则上是指仅有一个抽象方法的接口。
当然从jdk8之后,接口提供了默认方法和静态方法,所以jdk8之后的函数式接口除了一个抽象方法之外也可以增加默认方法和静态方法。
@FunctionalInterface注解可选在函数式接口上,如果接口有有两个抽象方法则会编译出错,一般IDE软件会提示错误。
先来一个简单实例:
@FunctionalInterface
interface IMessage{
public void send(String msg);
}
public class A {
public static void main(String[] args) {
IMessage iMessage = msg -> System.out.println("发送信息:"+msg);
iMessage.send("连接成功");
}
}
lambda表达式意在简化函数式接口的实现,那么函数式接口的原始操作是什么呢?我们来从接口和接口实现来一步一步做简化
-
1、最原始的操作是,新建一个实现类去实现接口。
interface IMessage{ //定义接口
public void send(String msg);
}
class MessageImpl implements IMessage{ //接口实现
@Override
public void send(String msg) {
System.out.println("发送信息:"+msg);
}
}
public class A {
public static void main(String[] args) {
IMessage i = new MessageImpl();
i.send("连接成功");
}
}
-
2、将上面的代码转为匿名内部类方式
@FunctionalInterface
interface IMessage{
public void send(String msg);
}
public class A {
public static void main(String[] args) {
IMessage i = new IMessage() { //匿名内部类
@Override
public void send(String msg) {
System.out.println("发送信息:"+msg);
}
};
i.send("连接成功");
}
}
-
3、lambda表达式就是针对只有一个抽象方法的接口(函数式接口)的简化方式,所以以上代码可以简为会:
@FunctionalInterface
interface IMessage{
public void send(String msg);
}
public class A {
public static void main(String[] args) {
IMessage i = msg -> { //lambda表达式
System.out.println("发送信息:"+msg);
};
i.send("连接成功");
}
}
-
4、代码块只有一行,可以继续简化:
@FunctionalInterface
interface IMessage{
public void send(String msg);
}
public class A {
public static void main(String[] args) {
IMessage i = msg -> System.out.println("发送信息:"+msg); //lambda表达式
i.send("连接成功");
}
}
lambda表达式简化函数式接口的过程就如上所示。下面来讲讲lambda的几种表达样式:
无参无返回 | () -> { 语句; } |
无参有返回 | () -> { return ; } |
有参无返回 | (参数1,参数2,...) -> { 语句; } |
有参有返回 | (参数1,参数2,...) -> { return ; } |
-> 符号之前的是入参,之后的是执行代码块
其中无参数必须明确标识出双括号()->;
多个参数必须采用括号并用逗号分隔(a,b,c...)->;
参数只有一个可以不用括号,直接写参数 msg ->;
代码块{} 如果只有一条语句可以不用大括号。
另java内置有一些常用的函数式接口
- supplier(供应商),无参有返回
@FunctionalInterface public interface Supplier<T> { T get(); }
-
Consumer(消费者),有参无返回
@FunctionalInterface public interface Consumer<T> { void accept(T t); }
- Function,有参有返回,接收参数类型T返回类型R
@FunctionalInterface public interface Function<T, R> { R apply(T t); }
- Predicate,有参返回布尔型
@FunctionalInterface public interface Predicate<T> { boolean test(T t); }
更多的请查询jdk源码或者文档
package java.util.function;
第二点我们来说说方法引用
方法引用也是针对函数式接口来说,引用:函数式接口中的抽象方法 引用 其他方法,简单来说,就是函数式接口中的方法引用另一个具体方法。
方法引用最重要的一点是,接口中抽象方法中的参数类型数量要和被引用方法中的参数类型数量完全一致。
当然对于多参数BiFunction<T, U, R>接口,T、U是传入参数,R是返回参数,传入参数,第一个T可以作为this调用
BiFunction<String,String ,Integer> f = String::compareTo;
BiFunction<String,String ,Integer> f = (a,b)->a.compareTo(b);
//public int compareTo(String anotherString) 》》》》》 a.comareTo(b)
方法引用的目的是复用已经存在的方法,减少代码量。
根据具体方法所在的位置可以会为:
1.引用普通方法:先要实例化对象再调用方法 实例对象::普通方法
2.引用静态方法:直接调用类方法 类::静态方法
3.引用构造方法:返回的是一个类的实例(对象) 类::new
@FunctionalInterface
interface IMessage{
public void send(String msg);
}
@FunctionalInterface
interface ICreat<R>{
public R creat();
}
class Person{
public Person() { //构造方法
System.out.println("构造方法");
}
public void print(String str){ //普通方法
System.out.println(str);
}
public static void print2(String str){ //静态方法
System.out.println(str);
}
}
public class A {
public static void main(String[] args) {
IMessage i = new Person()::print; //引用普通方法
i.send("普通方法");
IMessage i2 = Person::print2; //引用静态方法
i2.send("静态方法");
ICreat<Person> iCreat = Person::new; //引用构造方法,一般是返回的是类的实例
Person person = iCreat.creat();
}
}