Lambda代码分析

():没有内容,方法形参为空
->:箭头指向要做的事情
{}:代码块,为方法体的内容

格式:

  1. (形式参数) -> {代码块}
  • 形式参数:
    • 有多个的时候逗号隔开;没有参数为空
  • ->:
    • 英文,中画线、大于符号组成,固定写法。指向代码块
  • 代码块:
    • 事情逻辑

线程启动

实现Runnable接口

(1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

(2)创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

(3)调用线程对象的start()方法来启动该线程。

  1. public class RunnableThread implements Runnable{
  2. @Override
  3. public void run() {
  4. System.out.println("线程启动成功咯~~");
  5. }
  6. }
  • 启动代码:
  1. RunnableThread rt = new RunnableThread();
  2. Thread thread = new Thread(rt);
  3. thread.start();

匿名内部类改进

  1. new Thread(new Runnable() {
  2. @Override
  3. public void run() {
  4. System.out.println("线程启动成功咯~~");
  5. }
  6. }).start();

lambda改进

  1. new Thread(()->System.out.println("线程启动成功咯~~")).start();

Lambda格式

匿名内部类重写run()

  • 方法形式参数为空,调用方法时不需要传递参数
  • 方法返回值类型为void,方法执行没有结果返回
  • 方法体中内容,为事情逻辑

Lambda使用前提

  • 接口
  • 接口有且只有一个抽象方法

Lambda示例

无参无返回值

  1. public interface AnonyInterface {
  2. public abstract void show();
  3. }
  1. public class AnonyInterfaceTest {
  2. //假设已有下面方法
  3. /**
  4. *
  5. * @param anonyInterface
  6. * 形参是接口体的引用,调用接口的show方法
  7. * 方法的参数是接口类型,则在调用该方法时,需要创建并传递一个实现此接口类型的对象
  8. * 该方法在运行时会调用到参数对象中所实现的方法
  9. */
  10. //接口类型的引用指向实现类型的对象,形成了多态
  11. public static void test(AnonyInterface anonyInterface){
  12. //编译阶段调用父类版本,运行调用实现类重写的版本
  13. anonyInterface.show();
  14. }
  15. public static void main(String[] args) {
  16. // AnonyInterfaceTest.test(new AnonyInterface() );//接口不能实例化
  17. AnonyInterfaceTest.test(new AnonyInterfaceImpl());
  18. System.out.println("-----------使用匿名内部类--------");
  19. //使用匿名内部类的语法格式来得到接口类型的引用,格式为:接口/父类类型 引用变量名 = new 接口/父类类型(){ 方法重写 };
  20. AnonyInterface anonyInterface = new AnonyInterface() {
  21. @Override
  22. public void show() {
  23. System.out.println("匿名内部类,虽然很抽象~");
  24. }
  25. };
  26. AnonyInterfaceTest.test(anonyInterface);
  27. AnonyInterface anonyInterface1 = ()->System.out.println("匿名内部类lambda,虽然很抽象~");
  28. AnonyInterfaceTest.test(anonyInterface1);
  29. }
  30. }

无参有返回值

有参无返回值

有一个参数无返回值

  1. public interface OneInterface {
  2. public abstract void sleep(String place);
  3. }
  1. public class AnonyInterfaceTest {
  2. //接口类型的引用指向实现类型的对象,形成了多态
  3. public static void sleepTest(OneInterface oneInterface){
  4. //编译阶段调用父类版本,运行调用实现类重写的版本
  5. oneInterface.sleep("小明家");
  6. }
  7. public static void main(String[] args) {
  8. sleepTest(new OneInterface() {
  9. @Override
  10. public void sleep(String place) {
  11. System.out.println("今天晚上睡在:"+place);//今天晚上睡在:小明家
  12. }
  13. });
  14. sleepTest((String place)->{
  15. System.out.println("今天晚上睡在:"+place);//今天晚上睡在:小明家
  16. });
  17. }
  18. }

有多个参数无返回值

  1. public interface SumInterface {
  2. public abstract void add(int a, int b);
  3. }
  1. public class AnonyInterfaceTest {
  2. public static void addTest(SumInterface sumInterface){
  3. //编译阶段调用父类版本,运行调用实现类重写的版本
  4. sumInterface.add(3,5);
  5. }
  6. public static void main(String[] args) {
  7. addTest(new SumInterface() {
  8. @Override
  9. public void add(int a, int b) {
  10. int i = a + b;
  11. System.out.println("加法的结果:"+ i);
  12. }
  13. });
  14. addTest((int a, int b) -> {
  15. int i = a + b;
  16. System.out.println("加法的结果:"+ i);
  17. });
  18. }
  19. }

有参数有返回值

  1. public interface SubInterface {
  2. public abstract int sub(int a, int b);
  3. }
  1. public class AnonyInterfaceTest {
  2. public static void subTest(SubInterface subInterface){
  3. //编译阶段调用父类版本,运行调用实现类重写的版本
  4. int sub = subInterface.sub(3, 5);
  5. System.out.println("结果:"+sub);
  6. }
  7. public static void main(String[] args) {
  8. subTest((int a, int b) -> {
  9. return a - b;
  10. });
  11. }
  12. }

省略模式

  • 参数类型可以省略
  • 多个参数不能只省略一个
  1. addTest((a, b) -> {
  2. int i = a + b;
  3. System.out.println("省略参数类型加法的结果:"+ i);//省略参数类型加法的结果:8
  4. });
  5. sleepTest((place)->{
  6. System.out.println("省略参数类型今天晚上睡在:"+place);//省略参数类型今天晚上睡在:小明家
  7. });
  • 如果参数类型有且只有一个,则小括号省略
  1. sleepTest(place->{
  2. System.out.println("省略参数类型及小括号今天晚上睡在:"+place);//省略参数类型及小括号今天晚上睡在:小明家
  3. });
  • 若代码块只有一句,可省略大括号、分号
  1. sleepTest(place->
  2. //都省略今天晚上睡在:小明家
  3. System.out.println("都省略今天晚上睡在:"+place)
  4. );
  • 如果有return,则return也要省略掉
  1. subTest((a,b)-> a-b);

注意事项⚠️:

  • 使用Lambda必须有接口,并且要求接口中有且仅有一个抽象方法

前面声明的接口,注释掉方法,对应标红,如果复制多写一个方法,对应同样报错。

  • 必须有上下文环境,才能推导出Lambda对应接口
  1. new Thread(new Runnable() {
  2. @Override
  3. public void run() {
  4. System.out.println("线程启动成功咯~~");
  5. }
  6. }).start();
  7. //根据局部变量赋值 知道Lambda对应接口
  8. Runnable r = ()->System.out.println("线程启动成功咯~~");
  9. new Thread(r).start();
  10. //根据调用方法的参数 知道Lambda对应接口
  11. new Thread(()->System.out.println("线程启动成功咯~~")).start();

根据构造方式来推断lambda表达式的是Runnable的

  • 匿名内部类运行以后产生单独的字节码文件,lambda表达式不产生单独的字节码文件

Lambda - 图1