一个小栗子
为了更加深刻的理解lambda表达式,写了如下一个栗子:
package com.nrsc.lambda.MoneyDemo;
import java.text.DecimalFormat;
@FunctionalInterface
interface FormatInterface {
String formatNum(int i); //格式化数字的方法
}
//继承接口的方式
class FormatClass1 implements FormatInterface {
@Override
public String formatNum(int i) {
DecimalFormat decimalFormat = new DecimalFormat("#,###");
String format = decimalFormat.format(i);
return format;
}
}
//继承接口+链式编程的方式
class FormatClass2 implements FormatInterface {
@Override
public String formatNum(int i) {
//链式编程
return new DecimalFormat("#,###").format(i);
}
}
class MyMoney {
private int money;
public MyMoney(int money) {
this.money = money;
}
public void printMoney(FormatInterface formatInterface) {
System.out.println("我的存款是:" + formatInterface.formatNum(this.money));
}
}
public class MoneyDemo {
public static void main(String[] args) {
MyMoney myMoney = new MyMoney(8888888);
System.out.println("-----继承接口的方式-----");
FormatInterface f1 = new FormatClass1();
myMoney.printMoney(f1);
System.out.println("-----继承接口+链式编程的方式-----");
FormatInterface f2 = new FormatClass2();
myMoney.printMoney(f2);
System.out.println("-----匿名内部类的方式----");
myMoney.printMoney(new FormatInterface() {
@Override
public String formatNum(int i) {
return new DecimalFormat("#,###").format(i);
}
});
/**
* lambda表达式1----对应于继承接口方式
*/
System.out.println("-----lambda表达式方式1-----");
myMoney.printMoney(i -> {
DecimalFormat decimalFormat = new DecimalFormat("#,###");
return decimalFormat.format(i);
});
/**
* lambda表达式2----对应于继承接口+链式编程的方式(如果一句话可以搞定的话,可以省去return和大括号{})
*/
System.out.println("-----lambda表达式方式2-----");
myMoney.printMoney(i -> { return new DecimalFormat("#,###").format(i);});
myMoney.printMoney(i -> new DecimalFormat("#,###").format(i));
/**
* 当然假如我们的lambda表达式写成下面的样子的话,肯定结果就是"我的存款是:8888888英镑"
*/
System.out.println("======干点别的事情======");
myMoney.printMoney(i -> i + "英镑"); }
}
运行结果如下:
我们可以看到在上面使用的lambda表达式其实就相当于一个匿名内部类,但与匿名内部类相比,它不用指定(或者说知道)具体接口的名称,也不用指定(或者说知道)接口中具体要重写的方法,只需要知道其输入的是什么,要输出的是什么就可以了-----当然还有一个比较厉害的地方是假如这个输出用一句话就可以搞定的话,完全可以省去return和大括号{}.
函数式接口的引入
按照上面的结论,既然lambda表达式根本不关心具体是实现的是哪个接口,即他不需要知道接口的具体名字,也不需要知道接口内具体的方法, 它只需要知道其输入是什么,输出是什么, 那我们就完全没必要去实际地定义这样一个接口,只要有那么一个通用的接口,它的输入是我们想输入的值,它的输出是我们想输出的结果就可以了.-----JDK为我们提供了一些这样的函数式接口 (以后可能会细说,下面仅仅做一个小栗子),于是上面的代码我们就可以用JDK给我们提供的函数式接口改写成下面的样子:
请看如下代码:
package com.nrsc.lambda.MoneyDemo1;
import java.text.DecimalFormat;
import java.util.function.Function;
//没必要定义该接口
@FunctionalInterface
interface FormatInterface {
String formatNum(int i); //格式化数字的方法 ----输入值为int类型,输出值类型为String
}
class MyMoney {
private int money;
public MyMoney(int money) {
this.money = money;
}
//使用函数式接口Function<Integer, String>
//与我们定义的FormatInterface一样,它需要输入值为一个Integer类型,输出值类型为String
public void printMoney(Function<Integer, String> formatInterface) {
System.out.println("我的存款是:" + formatInterface.apply(this.money));
}
}
public class MoneyDemo {
public static void main(String[] args) {
MyMoney myMoney = new MyMoney(8888888);
/**
* 可以得到与上面栗子一样的结果
*/
myMoney.printMoney(i -> new DecimalFormat("#,###").format(i));
}
}
运行结果如下: