一 . lambda的使用条件 ---- 函数式接口
如果一个接口之中仅仅只有一个抽象的方法,那么我们就称这种接口为函数式接口.
首先我们看看JDK之中的函数式的接口.
@FunctionalInterface public interface Runnable { public abstract void run(); }
上面的接口就是我们最常用的Runnable接口,在JDK8之后,我们发现在该接口之中增加了一个@FunctionalInterface注解,用来表示这个接口是一个函数式的接口.
那么,函数式接口的注解和函数式接口有什么关系呢?其实这个注解是用来约束在编译期发现该接口的定义是否正确的接口,我们判断一个接口是否是函数接口的条件
永远都是是否仅仅只有一个抽象的方法.
二 . 匿名内部类
在JDK8之前,我们怎么常常在代码使用匿名内部类来完成一个对象的一次性的创建.
如下:
new Thread(new Runnable() { @Override public void run() { for(;;) System.out.println("Thread is running..."); } }).start();
我们使用匿名内部类实际上创建了一个接口的实例,但是上面的代码之中存在很多的模板代码,因此在jdk8之中出现了lambda表达式帮助我们实现上述代码的简化.
如下:
new Thread(()-> { for(;;) System.out.println("Thread is running...");}) .start();
我们发现上述的代码比之前的匿名内部类的方式代码简化了很多.
三.匿名内部类是否已经死亡?
在使用lambda表达式之前,我们首先需要知道lambda表达式的本质到底是什么?
看下面的代码:
Runnable able = ()->{System.out.println("Thread is running...");};
我们能够看到lambda表达式本质上就是一个接口的实例对象,只是从语法的角度上进行了简化而已.
说到接口,我们上面提到了函数式接口(仅仅只含有一个抽象方法的接口),没错,lambda表达式仅仅只能替换此类接口的实例.
说到现在,我们已经知道下面的事实:
[1]lambda表达式本身就是一个接口的实例对象而已.
[2]lambda表达式仅仅只能适用在函数式接口之中.
匿名内部类依然存在,只是一部分功能交给lambda表达式更加合适而已.
四 .行为函数
方法,我们在其他的语言之中常常称为函数,本质上函数就是将一组参数进行处理,然后返回一个值的一段代码而已.
我们可以这样的描述函数(方法): [入参] ---------------> [返回值].
我们从这个角度上看,函数除了实现的逻辑不通之外,对外暴露出来的最大的不同就是参数和返回值.
因此,我们可以将参数和返回作为函数分类的一种标准.
函数执行的逻辑我们称为一种行为.
我们看下面的一个例子:
/** * 我们定义了一个接口 * @author JieYun * */ static interface TestExec{ void exec(); } //本类之中的核心方法 public static void exec(TestExec demo) { demo.exec(); } public static void main(String[] args) { exec(new TestExec() { @Override public void exec() { System.out.println("first demo"); } }); exec(new TestExec() { @Override public void exec() { System.out.println("second demo"); } }); }
在上面的例子之中,我们传递的不同的实例,然后产生的不同行为,我们看看我们传递的参数到底是什么? 没错,就是一个内名内部类的对象,在这里实际也是一个lambda表达式了.
现在,我们就可以了解到lambda表达式就是一个行为参数.