zoukankan      html  css  js  c++  java
  • JDK1.8新特性之(一)--Lambda表达式

           近期由于新冠疫情的原因,不能出去游玩,只能在家呆着。于是闲来无事,开始阅读JDK1.8的源代码。在开始之前也查询了以下JDK1.8的新特性,有针对性的开始了这段旅程。

    只看不操作,也是不能心领神会的。而且好脑子不如烂笔头。在这里记载一下自己的学习成果。也算是做一下总结吧。

    在正文开始之前先看看JDK1.8都有哪些新特性?

    1.Lambda表达式

    2.方法引用

    3.函数式接口

    4.默认方法

    5.Stream

    6.Optional类

    7.Nashorm javascript引擎

    8.新的日期时间API

    9.Base64

    这篇文章先来学习第一个特性--Lambda表达式。

    话不多说,下面正式开始学习!

    (一)首先介绍以下Lambda表达式是啥?

    Lambda表达式也称作闭包,允许把函数作为一个方法的参数,使用Lamba表达式可以使代码变得更加简洁。

    (二)Lambda表达式的语法

    (参数) -> {代码块}

    (三)Lambda表达式的特性

    1.可选类型声明:参数的类型可以省,编译器自动识别数据类型。
    2.可选的参数圆括号:参数只有一个时候可以省略圆括号。
    3.可选的代码块大括号:代码块只有一行的时候可以省略大括号。
    4.可选的返回关键字:代码块只有一行且有返回结果,那么return也可以省略。
    (四)实例

    书写测试类之前先定义以下两个内部接口,供测试时使用

    MathOperation是用于计算数值的接口。

    Service是用于提示某些信息的接口。

    1 //定义数学操作接口
    2 interface MathOperation{
    3     Integer operation(Integer i1,Integer i2);
    4 }
    5 
    6 //定义服务接口
    7 interface Service{
    8     void sayHello(String message);
    9 }

    为了便于理解Lambda表达式和更加突出其优点,先用普通的书写方式实现MathOpertation的加法,减法,乘法,除法。

     1 //加法
     2 MathOperation mathOperation1 = new MathOperation() {
     3     @Override
     4     public Integer operation(Integer i1, Integer i2) {
     5         return i1 + i2;
     6     }
     7 };
     8 System.out.println("1+2=" + mathOperation1.operation(1,2));
     9 
    10 //减法
    11 MathOperation mathOperation2 = new MathOperation() {
    12     @Override
    13     public Integer operation(Integer i1, Integer i2) {
    14         return i1 - i2;
    15     }
    16 };
    17 System.out.println("4-3=" + mathOperation2.operation(4,3));
    18 
    19 //乘法
    20 MathOperation mathOperation3 = new MathOperation() {
    21     @Override
    22     public Integer operation(Integer i1, Integer i2) {
    23         return i1 * i2;
    24     }
    25 };
    26 System.out.println("5*6=" + mathOperation3.operation(5,6));
    27 
    28 //除法
    29 MathOperation mathOperation4 = new MathOperation() {
    30     @Override
    31     public Integer operation(Integer i1, Integer i2) {
    32         return i1 / i2;
    33     }
    34 };
    35 System.out.println("8/2=" + mathOperation4.operation(8,2));

    结果:

    1+2=3
    4-3=1
    5*6=30
    8/2=4

    最先用Lambda表达式的标准实现方式(没有任何省略简写)

     1 //加法
     2 MathOperation mathOperation9 = (Integer i1,Integer i2) -> {return i1 + i2;};
     3 System.out.println("1+2= " + mathOperation9.operation(1,2));
     4 
     5 //减法
     6 MathOperation mathOperation10 = (Integer i1,Integer i2) -> {return i1 - i2;};
     7 System.out.println("4-3= " + mathOperation10.operation(4,3));
     8 
     9 //乘法
    10 MathOperation mathOperation11 = (Integer i1,Integer i2) -> {return i1 * i2;};
    11 System.out.println("5*6= " + mathOperation11.operation(5,6));
    12 
    13 //除法
    14 MathOperation mathOperation12 = (Integer i1,Integer i2) -> {return i1 / i2;};
    15 System.out.println("8/2= " + mathOperation12.operation(8,2));

    结果:

    1+2= 3
    4-3= 1
    5*6= 30
    8/2= 4

    对比上面以前的写法和Lambda表达式的写法,不难看出,从代码量上减少了很多,变得更加简洁。

    从深层次的比较就会发现,Lambda表达式替代的就是

    new MathOperation() {

        XXXXX//此处省略

    };

    部分由此得出结论:Lambda表达式的实质就是匿名内部类

    接下来逐一用实例来说明Lambda的特性。

    1.可选类型声明:参数的类型可以省,编译器自动识别数据类型。

     1 //加法
     2 MathOperation mathOperation9 = (i1,i2) -> {return i1 + i2;};
     3 System.out.println("1+2= " + mathOperation9.operation(1,2));
     4 
     5 //减法
     6 MathOperation mathOperation10 = (i1,i2) -> {return i1 - i2;};
     7 System.out.println("4-3= " + mathOperation10.operation(4,3));
     8 
     9 //乘法
    10 MathOperation mathOperation11 = (i1,i2) -> {return i1 * i2;};
    11 System.out.println("5*6= " + mathOperation11.operation(5,6));
    12 
    13 //除法
    14 MathOperation mathOperation12 = (i1,i2) -> {return i1 / i2;};
    15 System.out.println("8/2= " + mathOperation12.operation(8,2));

    结果:

    1+2= 3
    4-3= 1
    5*6= 30
    8/2= 4

    2.可选的参数圆括号:参数只有一个时候可以省略圆括号。

    1 //省略版表达式
    2 Service service2 = message -> System.out.println("Hello," + message);
    3 service2.sayHello("Lambda表达式!");

    结果:

    Hello,Lambda表达式!

    3.可选的代码块大括号:代码块只有一行的时候可以省略大括号。

    4.可选的返回关键字:代码块只有一行且有返回结果,那么return也可以省略。

     1 //加法
     2 MathOperation mathOperation13 = (Integer i1,Integer i2) -> i1 + i2;
     3 System.out.println("1+2= " + mathOperation13.operation(1,2));
     4 
     5 //减法
     6 MathOperation mathOperation14 = (Integer i1,Integer i2) -> i1 - i2;
     7 System.out.println("4-3= " + mathOperation14.operation(4,3));
     8 
     9 //乘法
    10 MathOperation mathOperation15 = (Integer i1,Integer i2) -> i1 * i2;
    11 System.out.println("5*6= " + mathOperation15.operation(5,6));
    12 
    13 //除法
    14 MathOperation mathOperation16 = (Integer i1,Integer i2) -> i1 / i2;
    15 System.out.println("8/2= " + mathOperation16.operation(8,2));

    结果:

    1+2= 3
    4-3= 1
    5*6= 30
    8/2= 4

    Lambda表达式除了上面几个特性之外还有几个地方需要注意。

    1)Lambda表达式内部可以访问外部的局部变量。

    2)Lambda表达式被使用的外部局部变量默认是final类型的,不能修改其值,否则报错。

    3)Lambda表达式的内部使用的变量名称不能和外部使用的局部变量名称一样,否则会报错。

    1)实例如下

     1 /**
     2  * Lambda表达式内部可以访问外层的局部变量
     3  */
     4 //显性final
     5 final String pre_Str1 = "Test1";
     6 Service service3 = message -> System.out.println("显性final:" + pre_Str1 + message);
     7 service3.sayHello(" Jay");

    执行结果:

    显性final:Test1 Jay

    2)实例如下

         当对变量pre_Str2进行修改后,会出现编译错误:local variables referenced from a lambda expression must be final or effectively final。由此说明,引用的变量必须是final类型的。

     1 //隐形final
     2 String pre_Str2 = "Test2";
     3 Service service4 = message -> System.out.println("隐形final:" + pre_Str2 + message);
     4 service4.sayHello(" Jay");
     5 
     6 /**
     7  * Lambda表达中被使用的外部变量默认是final类型的。也就是说不能修改变量的值。
     8  * 如果试图修改变量的值则会报如下错误
     9  * Error:local variables referenced from a lambda expression must be final or effectively final
    10  */
    11 //pre_Str2 ="aaaaa";

    3)实例如下

      当在Lambda表达式中使用外部局部变量pre_Str3的时候,编译器报错:ariable pre_Str3 is already defined in method main(java.lang.String[])。由此说明变量的名称不能相同。

    1 /**
    2  * Lambda表达式的局部变量不可以和外部变量名称相同。
    3  * 如果Lambda表达式的局部变量和外部变量名称相同则报错。错误信息如下。
    4  * Error:variable pre_Str3 is already defined in method main(java.lang.String[])
    5  */
    6 // String pre_Str3 = "Test3";
    7 // Service service5 = pre_Str3 -> System.out.println("变量名测试:" + pre_Str2 + pre_Str3);
    8 // service5.sayHello(" Jay");

    以上就是我对Lambda表达式的理解。如果有理解不对或者记述错误的地方欢迎指正,互相学习,提升自己。

    下面是我测试的完整类和完整结果。有需要的可以参考。

      1 package com.dream.test.JDK8speciality;
      2 
      3 import java.util.*;
      4 
      5 /**
      6  * @author 匠人码农
      7  * @date 2020/05/04 21:31
      8  * 概要:
      9  *     Lambda表达式理解
     10  *     Lambda格式
     11  *     (参数) -> {代码块}
     12  *     注:
     13  *       1.可选类型声明:参数的类型可以省,编译器自动识别数据类型。
     14  *       2.可选的参数圆括号:参数只有一个时候可以省略圆括号。
     15  *       3.可选的代码块大括号:代码块只有一行的时候可以省略大括号。
     16  *       4.可选的返回关键字:代码块只有一行且有返回结果,那么return也可以省略。
     17  *       5.Lambda表达式的局部局部变量默认是final类型的。
     18  *       6.Lambda表达式内部可以引用Lambda表达式外部的局部变量,而且必须是final类型的。
     19  *       7.Lambda表达式内部的局部变量名称不可以和Lambda表达式外部的局部变量的名称一样。
     20  */
     21 
     22 public class LambdaTest {
     23     public static void main(String[] args) {
     24 
     25         //没有Lambda表达式之前实现MathOperation的operation方法
     26         System.out.println("***************************************************");
     27         System.out.println("* 没有Lambda表达式之前实现MathOperation的operation方法");
     28         System.out.println("***************************************************");
     29 
     30         //加法
     31         MathOperation mathOperation1 = new MathOperation() {
     32             @Override
     33             public Integer operation(Integer i1, Integer i2) {
     34                 return i1 + i2;
     35             }
     36         };
     37         System.out.println("1+2=" + mathOperation1.operation(1,2));
     38 
     39         //减法
     40         MathOperation mathOperation2 = new MathOperation() {
     41             @Override
     42             public Integer operation(Integer i1, Integer i2) {
     43                 return i1 - i2;
     44             }
     45         };
     46         System.out.println("4-3=" + mathOperation2.operation(4,3));
     47 
     48         //乘法
     49         MathOperation mathOperation3 = new MathOperation() {
     50             @Override
     51             public Integer operation(Integer i1, Integer i2) {
     52                 return i1 * i2;
     53             }
     54         };
     55         System.out.println("5*6=" + mathOperation3.operation(5,6));
     56 
     57         //除法
     58         MathOperation mathOperation4 = new MathOperation() {
     59             @Override
     60             public Integer operation(Integer i1, Integer i2) {
     61                 return i1 / i2;
     62             }
     63         };
     64         System.out.println("8/2=" + mathOperation4.operation(8,2));
     65         //Lambda表达式
     66         System.out.println("***************************************************");
     67         System.out.println("* Lambda表达式写法实现MathOperation的operation方法");
     68         System.out.println("***************************************************");
     69 
     70         // 标准的Lambda表达式
     71         System.out.println("*****标准的Lambda表达式书写方式*****");
     72         //加法
     73         MathOperation mathOperation5 = (Integer i1,Integer i2) -> {return i1 + i2;};
     74         System.out.println("1+2= " + mathOperation5.operation(1,2));
     75 
     76         //减法
     77         MathOperation mathOperation6 = (Integer i1,Integer i2) -> {return i1 - i2;};
     78         System.out.println("4-3= " + mathOperation6.operation(4,3));
     79 
     80         //乘法
     81         MathOperation mathOperation7 = (Integer i1,Integer i2) -> {return i1 * i2;};
     82         System.out.println("5*6= " + mathOperation7.operation(5,6));
     83 
     84         //除法
     85         MathOperation mathOperation8 = (Integer i1,Integer i2) -> {return i1 / i2;};
     86         System.out.println("8/2= " + mathOperation8.operation(8,2));
     87 
     88         // 省略参数类型
     89         System.out.println("*****省略参数类型*****");
     90         //加法
     91         MathOperation mathOperation9 = (i1,i2) -> {return i1 + i2;};
     92         System.out.println("1+2= " + mathOperation9.operation(1,2));
     93 
     94         //减法
     95         MathOperation mathOperation10 = (i1,i2) -> {return i1 - i2;};
     96         System.out.println("4-3= " + mathOperation10.operation(4,3));
     97 
     98         //乘法
     99         MathOperation mathOperation11 = (i1,i2) -> {return i1 * i2;};
    100         System.out.println("5*6= " + mathOperation11.operation(5,6));
    101 
    102         //除法
    103         MathOperation mathOperation12 = (i1,i2) -> {return i1 / i2;};
    104         System.out.println("8/2= " + mathOperation12.operation(8,2));
    105 
    106         // 省略大括号省略return
    107         System.out.println("*****省略大括号和return*****");
    108         //加法
    109         MathOperation mathOperation13 = (Integer i1,Integer i2) -> i1 + i2;
    110         System.out.println("1+2= " + mathOperation13.operation(1,2));
    111 
    112         //减法
    113         MathOperation mathOperation14 = (Integer i1,Integer i2) -> i1 - i2;
    114         System.out.println("4-3= " + mathOperation14.operation(4,3));
    115 
    116         //乘法
    117         MathOperation mathOperation15 = (Integer i1,Integer i2) -> i1 * i2;
    118         System.out.println("5*6= " + mathOperation15.operation(5,6));
    119 
    120         //除法
    121         MathOperation mathOperation16 = (Integer i1,Integer i2) -> i1 / i2;
    122         System.out.println("8/2= " + mathOperation16.operation(8,2));
    123 
    124         //没有Lambda表达式之前的写法
    125         Service service0 = new Service() {
    126             @Override
    127             public void sayHello(String message) {
    128                 System.out.println("hello: " + message);
    129             }
    130         };
    131         service0.sayHello("没有Lambda表达式之前的写法!!!");
    132 
    133         //完整版表达式
    134         Service service1 = (message) -> {
    135             System.out.println("this is my " + message);
    136         };
    137         service1.sayHello("Lambda表达式测试!");
    138 
    139         //省略版表达式
    140         Service service2 = message -> System.out.println("Hello," + message);
    141         service2.sayHello("Lambda表达式!");
    142 
    143         /**
    144          * Lambda表达式内部可以访问外层的局部变量
    145          */
    146         //显性final
    147         final String pre_Str1 = "Test1";
    148         Service service3 = message -> System.out.println("显性final:" + pre_Str1 + message);
    149         service3.sayHello(" Jay");
    150 
    151         //隐形final
    152         String pre_Str2 = "Test2";
    153         Service service4 = message -> System.out.println("隐形final:" + pre_Str2 + message);
    154         service4.sayHello(" Jay");
    155 
    156         /**
    157          * Lambda表达中被使用的外部变量默认是final类型的。也就是说不能修改变量的值。
    158          * 如果试图修改变量的值则会报如下错误
    159          * Error:local variables referenced from a lambda expression must be final or effectively final
    160          */
    161         //pre_Str2 ="aaaaa";
    162 
    163         /**
    164          * Lambda表达式的局部变量不可以和外部变量名称相同。
    165          * 如果Lambda表达式的局部变量和外部变量名称相同则报错。错误信息如下。
    166          * Error:variable pre_Str3 is already defined in method main(java.lang.String[])
    167          */
    168         //String pre_Str3 = "Test3";
    169         //Service service5 = pre_Str3 -> System.out.println("变量名测试:" + pre_Str2 + pre_Str3);
    170         //service5.sayHello(" Jay");
    171 
    172     }
    173 
    174     //定义数学操作接口
    175     interface MathOperation{
    176         Integer operation(Integer i1,Integer i2);
    177     }
    178 
    179     //定义服务接口
    180     interface Service{
    181         void sayHello(String message);
    182     }
    183 
    184 }
    测试类

    结果

     下一篇文章

    JDK1.8新特性之(二)--方法引用

  • 相关阅读:
    js处理select操作总结
    IntelliJ IDEA 下载 安装
    PropertiesConfiguration处理properties
    CentOS操作系统,安装完毕后只能在“命令行模式”下登陆,无法进入“图形化界面”
    java客户端Ip获取
    加载依赖的jar包在命令行编译和运行java文件
    request.getSession(true)和request.getSession(false)的区别
    Spring在web请求中定义编码(org.springframework.web.filter.CharacterEncodingFilter)
    java操作redis
    【http】生命周期和http管道技术 整理中
  • 原文地址:https://www.cnblogs.com/worthycoder/p/12838811.html
Copyright © 2011-2022 走看看