lambda表达式是java8推出的特性之一, 是一颗语法糖, 可以看成是一个匿名内部类的简化版(但是必须基于函数式接口, 后文中有说到), 用于写出更优雅的代码
注: 本篇博客适合于刚学习lambda表达式的小伙伴, 阅读本文需要一点匿名内部类相关知识
public interface Animal {
// 动物吃东西
void eat();
}
public static void main(String[] args) {
// 创建对象cat
Animal cat = new Animal() {
@Override
public void eat() {
System.out.println("猫吃老鼠");
}
};
cat.eat();
}
public static void main(String[] args) {
// 创建cat对象
Animal cat = () -> System.out.println("猫吃老鼠");
cat.eat();
}
可以看到, 在实现相同的功能时, 使用lambda语法可以使得代码异常的简洁
// lambda表达式语法
(Object obj1,Object obj2,Object obj3...)->{
// 方法体
return;
}
// 省略参数类型
(obj1,obj2,obj3...)->{
// 方法体
return;
}
// 省略小括号
obj1->{
// 方法体
return;
}
() -> System.out.println("方法体中只有一句代码")
// 该方法return一个true
() -> true
/**
* 函数式接口: 给接口上加上@FunctionInterface注解, 会检查接口是不是函数式接口, 不报错说明就是函数式接口
*/
@FunctionalInterface
interface Animal {
// 无参无返回值的抽象方法
void eat();
// 函数式接口中可以有其他方法, 但是抽象方法有且只能有一个
default void defaultMethod(){
System.out.println("我是jdk8的特性之一: default默认方法");
}
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
// lamdaba
Animal cat1 = () -> {
System.out.println("我是猫cat1, 我喜欢吃鱼");
System.out.println("我是猫cat1, 我喜欢抓老鼠");
};
cat1.eat();
// 省略模式:
// 若代码块中只有一句代码且方法返回值为void, 则可以省略大括号和分号
// 此处的分号是创建对象的分号, 方法体中的分号已经省略
Animal cat2 = () -> System.out.println("我是猫cat2, 我喜欢吃鱼, 也喜欢抓老鼠");
cat2.eat();
}
}
@FunctionalInterface
interface Animal {
// 只有一个参数, 无返回值
void eat(String food);
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
// lamdaba简写形式: 若是只有一个形参, 则可以不写小括号
Animal cat = food -> System.out.println("我是猫cat, 我喜欢吃" + food);
cat.eat("鱼和猫条");
}
}
@FunctionalInterface
interface Animal {
// 有多个参数, 无返回值
void eat(String food, int number);
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
// lamdaba
Animal cat = (food, num) -> System.out.println("我是猫cat, 我一次要吃" + num + "份" + food);
cat.eat("鱼", 5);
}
}
有返回值时, 不管有参无参, 跟返回值是void的方法中的区别在于方法体中有无return语句, 其他并无区别, 因此, 此处只演示多个参数有返回值的情况
@FunctionalInterface
interface Calculator {
// 将两个数字进行相加, 返回结果
int add(int number1, int number2);
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
// lamdaba
Calculator calculator = (num1, num2) -> {
System.out.println("加法运算...");
return num1+num2;
};
calculator.add(10, 5);
}
}
当方法体中有且只有一条返回语句时, 省略模式如下:
public static void main(String[] args) {
// 当方法体中只有一条return语句时, 省略模式如下
Calculator calculator = (num1, num2) -> num1 + num2;
calculator.add(10, 5);
}
我们先用常规的方式实现
public static void main(String[] args) {
// 创建一个线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程: "+Thread.currentThread().getName()+"启动了...");
}
}).start();
}
然而, 当你点进Runnable接口后会看见如下源码:
原来Runnable接口也是一个函数式接口, 因此我们可以直接使用lambda表达式来代替匿名内部类:
public static void main(String[] args) {
// 创建一个线程
new Thread(() -> System.out.println("线程: "+Thread.currentThread().getName()+"启动了...")).start();
}
总之, 只要方法参数中需要让我们传入一个函数式接口的对象, 那么我们就可以使用lambda表达式来将代码简化. 比如HashMap中提供的forEach(BiConsumer action)方法, 也是传入一个函数式接口的对象, 这样, 我们直接调用此方法, 再配合以lambda, 就可以用很简洁的代码对集合进行遍历了
匿名内部类是new一个新的对象出来, 在编译后会产生单独的一份.calss文件, Lambda表达式在编译时不会产生字节码文件, 在运行时才会动态生成字节码文件
原创作者: 笔记狂魔, 如有错误, 请多指正