在Java8 函数式编程初识之Lambda表达式中讲了如果一个接口中仅有一个待实现的方法则它可以用Lambda代替.我们把这种接口叫做函数式接口,我们可以在该接口上写上@FunctionalInterface注解标明它是个函数式接口,但是无论标不标,它都会被Java识别为函数式接口
package cn.monoy.demos3;
@FunctionalInterface
public interface FunctionalInterfaceDemo {
public void doSomething();
@Override
String toString();
}
所以在Java8中 Lambda 表达式的作用就是简化函数式接口,你会注意到,我在接口中写了一个Object类的方法toString(),这在Java8的函数式接口语法中是允许的,在用lambda 表达式的时候Java只会把表达式当成doSomething方法.也就是说在接口中声明Object类中的方法名不会影响这个接口成为一个函数式接口.
使用函数式接口的另一个好处就是可以用lambda表达式赋给一个接口声明的变量.
package cn.monoy.demos3;
public class Main {
public static void main(String[] args) {
//创建线程
Runnable run = () -> {
System.out.println("BlahBlahBlahBlah");
};
Thread thread = new Thread(run);
thread.start();
//我自己写的函数式接口
FunctionalInterfaceDemo fi = () -> {
System.out.println("BlahBlahBlahBlah");
};
fi.doSomething();
}
}
从如上代码可以看出,创建线程必须实现的Runnable接口也是一个函数式接口.我把同样的lambda表达式分别赋给了Runnable接口 和我自己写的FunctionalInterfaceDemo 接口,并不会发生什么错误.个人觉得这样的写法可以简化代码层级,使得可读性更好.当然,还是看个人喜好.
下面说说异常,在lambda表达式中的代码不可避免要遇到异常处理,如果在lambda表达式中遇到要处理异常.要么直接在表达式中try catch要么就在接口中声明的方法上面抛出,举例
package cn.monoy.demos3;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class Main {
public static void main(String[] args) {
FunctionalInterfaceDemo fi = () -> {
//直接在代码块中处理
try {
InputStream ins = new FileInputStream("test.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
};
fi.doSomething();
}
}
我在接口中给doSomething 添加了throws 声明抛出异常,则在调用doSomething 时处理此异常
package cn.monoy.demos3;
import java.io.FileInputStream;
import java.io.InputStream;
public class Main {
public static void main(String[] args) {
FunctionalInterfaceDemo fi = () -> {
InputStream ins = new FileInputStream("test.txt");
};
//在调用时处理异常 也可以选择继续抛出
try {
fi.doSomething();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}