1 基本使用
package com.example.shardingjdbcsimple;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class MainT {
public static void main(String[] args) {
// 需求分析
/*代码分析:
1. Thread类需要一个Runnable接口作为参数,其中的抽象方法run方法是用来指定线程任务内容的核心;
2.为了指定run方法体,不得不需要Runnable的实现类;
3.为了省去定义一个Runnable 的实现类,不得不使用匿名内部类
4.必须覆盖重写抽象的run方法,所有的方法名称,方法参数,方法返回值不得不都重写一遍,而且不能出错;
5.而实际上,我们只在乎方法体中的代码*/
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("新线程执行的代码:" + Thread.currentThread().getName());
}
}).start();
/*Lambda表达式的优点: 简化了匿名内部类的使用,语法更加简单。
匿名内部类语法冗余,体验了Lambda表达式后,发现Lambda表达式是简化置名内部类的一种方式。*/
new Thread(() -> {
System.out.println("新线程Lambda表达式..." + Thread.currentThread().getName());
}).start();
System.out.println("主线程中的代码:" + Thread.currentThread().getName());
/**
* 语法规则:
* (参数类型 参数名称) -> {}
* 格式说明: (参数类型 参数名称) : 参数列表
* {代码体}:方法体
* -> : 分割参数列表和方法体
*/
/**
* 无参数无返回值的练习1:
*/
goShow(new UserService() {
@Override
public void show() {
System.out.println("show方法执行了");
}
});
goShow(() ->{
System.out.println("Lambda: show方法执行了");
});
/**
* 有参有返回值的练习2:
*/
ArrayList<Person> personList = new ArrayList<>();
personList.add(new Person("zhoujielun", 35, 100));
personList.add(new Person("liudehua", 60, 110));
personList.add(new Person("zhouxingchi", 70, 120));
personList.add(new Person("goufucheng", 45, 180));
Collections.sort(personList, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
});
Collections.sort(personList, (o1, o2) -> {
return o1.getAge() - o2.getAge();
});
System.out.println(personList);
}
public static void goShow(UserService userService) {
userService.show();
}
}
/**
* @FunctionalInterface 这是是一个标识注解,被该注解修饰的接口只能声明一个抽象接口。
*/
@FunctionalInterface
interface UserService {
void show();
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Person{
private String name;
private Integer age;
private Integer height;
}
2 原理解析
Lambda表达式的原理是什么呢?
我们通过jdk自带的反编译工具查看:
javap -c -p 文件名.class
在这个反编译的源码中,我们看到了一个静态方法lambda$main$0()
;方法体中的代码是在lambda$main$0()
中执行的;
匿名内部类在编译的时候会生成一个class文件,Lambda表达式在程序运行的时候会形成一个类。
1.在类中新增了一个方法, 这个方法的方法体就是Lambda表达式中的代码
2.还会形成一个国名内部类,实现接口,重写抽象方法
3.在接口中重写方法会调用新生成的方法
3 省略写法
在lambda表达式的标准写法基础上,可以使用省略的规则为:
1.小括号内的参数类型可以省略
2.如果小括号内有且仅有一个参数,则小括号可以省略
3.如果大括号内有且仅有一个语句,可以同时省略大括号,return 关键字及语句分号。
package com.example.shardingjdbcsimple;
public class MainT {
public static void main(String[] args) {
goStudent((String name, Integer age) -> {
return name + age + " 666";
});
goStudent((name, age) -> name + age + " 666");
goOrder((String name) -> {
System.out.println(name);
return 999;
});
goOrder(name -> 666);
}
public static void goStudent(StudentService studentService) {
studentService.show("zhangsan", 11);
}
public static void goOrder(OrderService orderService) {
orderService.show("lisi");
}
}
interface StudentService {
String show(String name, Integer age);
}
interface OrderService {
Integer show(String name);
}
4 Lambda的使用前提
Lambda表达式的潘法是非常简洁的,但是ambda表达式不是随便使用的,使用时有几个条件要特别注意:
1.方法的参数或局部变量类型必须为按口才能使用Lambda
2.按口中有且仅有一个抽象方法(@FunctionalInterface)
5 Lambda与匿名内部类的对比
Lambda和匿名内部类的对比:
1.所需类型不一样
1.重名内部类的类型可以是类,抽象类,接口
2. Lambda表达式需要的类型必须是接口
2.抽象方法的数量不一-样
1.置名内部类所需的接口中的抽象方法的数量是随意的
2. Lambda表达式所需的接口中只能有一个抽象方法
3.实现原理不-样
1.医名内部类是在编泽后形成一个class
2. Lambda表达式是在程序运行的时候动态生成class