在Java8中新增了Lambda表达式,允许使用更简洁的代码创建只有一个抽象方法的接口(函数式接口即只有一个抽象方法的接口,通常用@FunctionalInterface注解)的实例,用于向方法中传递参数,听着可能比较抽象,可以看一下下面的例子。
Lambda表达式的写法
(形参列表)->{代码块}
举一个例子:
public class Lambda {
public static void main(String[] args) {
A a = new A();
// Lambda表达式
a.test("苹果", s->System.out.println(s));
// 创建一个匿名内部类作为参数传递
a.test("西瓜", new I()
{
public void eat(String s){
System.out.print(s);
}
}
);
}
}
// 类A中的方法将函数式接口作为参数
class A {
public void test(String s, I a){
a.eat("吃"+s);
}
}
// 函数式接口
interface I {
void eat(String s);
}
从上面的例子可以看出,当一个方法将一个函数式接口作为参数时,可以使用Lambda表达式简化代码。当不使用Lambda表达式时,我们需要传递一个函数式接口的实现类,最重要的就是实现函数式接口中的抽象方法,因为通常来说将函数式接口作为参数的方法需要调用函数式接口中的抽象方法。Lambda可以省略创建函数式接口实现类的代码,仅将函数式接口的抽象方法实现并作为参数即可。
Lambda简化代码的其他写法
1.形参列表中若只有一个参数,可以省略括号不写
2.代码块中若只有一行代码,可以省略花括号,若代码只有一行return语句,可以将return也省略不写。
举几个简单例子:
public class Lambda {
public static void main(String[] args) {
A a = new A();
// 省略参数括号和代码块的花括号
a.test("苹果", s -> System.out.println(s));
// 只有一行返回语句,可以省略return不写
a.count(2, c -> c);
}
}
// 类A中的方法将函数式接口作为参数
class A {
public void test(String s, I i){
i.eat("吃"+s);
}
public void count(int a, J j){
System.out.print("吃了"+j.count(a)+"个!");
}
}
// 函数式接口
interface I {
void eat(String s);
}
interface J {
int count(int a);
}
Lambda表达式的作用可以理解为实现一个函数式接口,当一个接口中有多个抽象方法时,再使用Lambda表达式就会出现错误,这个时候可以使用匿名内部类写法。
public class Lambda {
public static void main(String[] args) {
A a = new A();
// 省略参数括号和代码块的花括号
a.test("苹果", s -> System.out.println(s));
// 只有一行返回语句,可以省略return不写
// a.count(2, c -> c);
a.count(2, new J(){
@Override
public int count(int a) {
return a;
}
@Override
public int count2(int a) {
return 0;
}
});
}
}
// 类A中的方法将函数式接口作为参数
class A {
public void test(String s, I i){
i.eat("吃"+s);
}
public void count(int a, J j){
System.out.print("吃了"+j.count(a)+"个!");
}
}
// 函数式接口
@FunctionalInterface
interface I {
void eat(String s);
}
interface J {
int count(int a);
int count2(int a);
}
匿名内部类需要将接口中的所有抽象方法全部实现,这种做法通常是不常见的。
Lambda表达式其他的应用方法
I i = s -> System.out.print("吃"+s+'\n');
将Lambda表达式实现的函数式接口赋值给函数式接口
Object i = (I)s -> System.out.print("吃"+s+'\n');
使用强制类型转换后赋值给Object类,不加强制类型转换编译器无法判断Lambda表达式实现的是哪一个函数式接口。
匿名内部类和Lambda表达式的区别和联系
1.匿名内部类可以为任意接口创建实例,不管接口包含多少个抽象方法,只要匿名内部类实现所有的抽象方法即可;但Lambda表达式只能为函数式接口创建实例。
2.匿名内部类可以为抽象类甚至普通类创建实例。
3.匿名内部类实现的抽象方法的方法体允许调用接口中定义的默认方法,但Lambda表达式的代码块不允许调用接口中定义的默认方法。
关于Lambda的方法引用和构造器引用之后再补充。。。