java中lambda表达式的实现

朴灿烈づ我的快乐病毒、 2022-04-24 02:22 292阅读 0赞

一.示例代码

  1. package lambda.examples._02;
  2. import java.util.ArrayList;
  3. import java.util.Comparator;
  4. import java.util.List;
  5. public class App {
  6. List<Apple> getAppleList() {
  7. List<Apple> list = new ArrayList<Apple>();
  8. list.add(new Apple("green", 100));
  9. list.add(new Apple("red", 150));
  10. list.add(new Apple("green", 50));
  11. return list;
  12. }
  13. public void test() {
  14. List<Apple> list = getAppleList();
  15. list.sort(Comparator.comparing(Apple::getWeight));
  16. list.forEach(System.out::println);
  17. }
  18. public static void main(String[] args) {
  19. new App().test();
  20. }
  21. }
  22. class Apple {
  23. private String color;
  24. private int weight;
  25. public Apple(String color, int weight) {
  26. super();
  27. this.color = color;
  28. this.weight = weight;
  29. }
  30. @Override
  31. public String toString() {
  32. return "Apple [color=" + color + ", weight=" + weight + "]";
  33. }
  34. public String getColor() {
  35. return color;
  36. }
  37. public void setColor(String color) {
  38. this.color = color;
  39. }
  40. public int getWeight() {
  41. return weight;
  42. }
  43. public void setWeight(int weight) {
  44. this.weight = weight;
  45. }
  46. }

二.代码分析

输出如下:

  1. Apple [color=green, weight=50]
  2. Apple [color=green, weight=100]
  3. Apple [color=red, weight=150]

在test方法中我们使用了java8中的新特性lambda表达式,
list.sort()需要传入一个Comparator接口的实现类,在java8之前我们通常使用匿名内部类实现,类似这样

  1. list.sort(new Comparator<Apple>() {
  2. @Override
  3. public int compare(Apple a, Apple b) {
  4. return a.getWeight() > b.getWeight() ? 1 : (a.getWeight() < b.getWeight() ? -1 : 0);
  5. }
  6. });

可以看出来其实有用的就一行代码,还要写那么多,所以对于这种只有一个抽象方法的接口我们称之为函数式接口,我们直接用lambda表达式实现,代码如下:

  1. list.sort((a, b) -> a.getWeight() > b.getWeight() ? 1 : (a.getWeight() < b.getWeight() ? -1 : 0));

分析下什么意思,sort可以接受Comparator类型的接口实现类,Comparator是一个函数式接口,他的抽象方法是

  1. @Override
  2. public int compare(Apple a, Apple b) {
  3. return a.getWeight() > b.getWeight() ? 1 : (a.getWeight() < b.getWeight() ? -1 : 0);
  4. }

我们简写为

  1. (a, b) -> a.getWeight() > b.getWeight() ? 1 : (a.getWeight() < b.getWeight() ? -1 : 0)

即可
->意为goto,前面的是方法的参数,后面是结果,如果只有一行就不写return,否则需要用{}括起来,并且return返回值,例如:

  1. list.sort((a, b) -> {
  2. if (a.getWeight() > b.getWeight())
  3. return 1;
  4. if (a.getWeight() < b.getWeight())
  5. return -1;
  6. return 0;
  7. });

这里ab我们并不需要写类型,编译器会根据list的类型做推断

三.lambda如何实现

代码如下:

  1. package lambda.examples._02;
  2. import java.util.ArrayList;
  3. import java.util.Comparator;
  4. import java.util.List;
  5. public class App {
  6. List<Apple> getAppleList() {
  7. List<Apple> list = new ArrayList<Apple>();
  8. list.add(new Apple("green", 100));
  9. list.add(new Apple("red", 150));
  10. list.add(new Apple("green", 50));
  11. return list;
  12. }
  13. public void test() {
  14. List<Apple> list = getAppleList();
  15. list.sort(new Comparator<Apple>() {
  16. @Override
  17. public int compare(Apple a, Apple b) {
  18. return a.getWeight() > b.getWeight() ? 1 : (a.getWeight() < b.getWeight() ? -1 : 0);
  19. }
  20. });
  21. list.sort((a, b) -> a.getWeight() > b.getWeight() ? 1 : (a.getWeight() < b.getWeight() ? -1 : 0));
  22. list.forEach(System.out::println);
  23. }
  24. }
  25. class Apple {
  26. private String color;
  27. private int weight;
  28. public Apple(String color, int weight) {
  29. super();
  30. this.color = color;
  31. this.weight = weight;
  32. }
  33. @Override
  34. public String toString() {
  35. return "Apple [color=" + color + ", weight=" + weight + "]";
  36. }
  37. public String getColor() {
  38. return color;
  39. }
  40. public void setColor(String color) {
  41. this.color = color;
  42. }
  43. public int getWeight() {
  44. return weight;
  45. }
  46. public void setWeight(int weight) {
  47. this.weight = weight;
  48. }
  49. }
  50. package lambda.examples._02;
  51. import java.io.IOException;
  52. public class OtherApp {
  53. public static void main(String[] args) throws IOException {
  54. new App();
  55. System.in.read();
  56. }
  57. }

现在用OtherApp的main方法初始化一个App类型的对象(这是为了加载App类),然后阻塞住查看字节码

  1. java -classpath "%JAVA_HOME%/lib/sa-jdi.jar" sun.jvm.hotspot.HSDB

jps查看pid
在这里插入图片描述
使用hsdb attch 4744
打开Tools -> Class Brower
搜索App
在这里插入图片描述
查看class,发现其中有一个方法叫

  1. private static [synthetic] int lambda$0(lambda.examples._02.Apple, lambda.examples._02.Apple)@0x000000001da80b80;

synthetic表示这是编译器生成的方法

所以说lambda语句会在所在的类被加载时,被jvm解析为该类中的一个private static 方法,接收lambda语句中的参数并且返回 lambda语句 -> 后面的结果(如果有返回值)

Create .class File

执行

  1. javap -c -p App.class

结果如下:

  1. Compiled from "App.java"
  2. public class lambda.examples._02.App {
  3. public lambda.examples._02.App();
  4. Code:
  5. 0: aload_0
  6. 1: invokespecial #8 // Method java/lang/Object."<init>":()V
  7. 4: return
  8. .
  9. .
  10. .
  11. .
  12. .
  13. .
  14. private static int lambda$0(lambda.examples._02.Apple, lambda.examples._02.Apple);
  15. Code:
  16. 0: aload_0
  17. 1: invokevirtual #72 // Method lambda/examples/_02/Apple.getWeight:()I
  18. 4: aload_1
  19. 5: invokevirtual #72 // Method lambda/examples/_02/Apple.getWeight:()I
  20. 8: if_icmple 15
  21. 11: iconst_1
  22. 12: goto 31
  23. 15: aload_0
  24. 16: invokevirtual #72 // Method lambda/examples/_02/Apple.getWeight:()I
  25. 19: aload_1
  26. 20: invokevirtual #72 // Method lambda/examples/_02/Apple.getWeight:()I
  27. 23: if_icmpge 30
  28. 26: iconst_m1
  29. 27: goto 31
  30. 30: iconst_0
  31. 31: ireturn
  32. }

可以清晰的看到我们在lambda语句里定义的逻辑

所以

lambda语句会在类被jvm加载时解析为该类的private static 方法随之初始化

发表评论

表情:
评论列表 (有 0 条评论,292人围观)

还没有评论,来说两句吧...

相关阅读

    相关 java Lambda表达使用

    如题,因为博主也是最近才接触到Lambda表达式的(PS 在这里汗颜一会)。我并不会讲解它的原理,诚然任何一件事物如果理解原理的话,使用它必将更加容易。但博主在学习的时候,大多

    相关 JavaLambda表达使用

    简介 (译者注:虽然看着很先进,其实Lambda表达式的本质只是一个"[语法糖][Link 1]",由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同