深入理解Java8新特性之Lambda表达式的基本语法和自定义函数式接口

1.写在前面

目前我们学习Java主要用到的应该就是Java8了,或者说大部分企业当前使用的也是Java8。那么既然Java8的应用如此之广泛,一定有一些亮点所在:

  • Lambda 表达式
  • 函数式接口
  • 方法引用与构造器引用
  • Stream API
  • 接口中的默认方法与静态方法
  • 新时间日期API
  • 其他新特性

速度更快、代码更少(增加了新的语法 Lambda 表达式)、强大的 Stream API、便于并行、最大化减少空指针异常 Optional。

2.为什么要使用Lambda表达式?

Lambda 是一个 匿名函数 数,我们可以把 Lambda表达式理解为是 一段可以传递的 代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java语言表达能力得到了提升。

3.Lambda表达式的基本语法

Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “ -> ” , 该操作符被称为 Lambda 操作符或剪头操作符。

它将 Lambda 分为两个部分:

  • 左侧 :指定了 Lambda 表达式需要的所有参数。
  • 右侧 :指定了 Lambda 体,即 Lambda 表达式要执行的功能。

具体的就看下面的代码案例。

package com.szh.java8;

import org.junit.Test;

import java.util.Comparator;
import java.util.function.Consumer;

/**
 * Lambda 表达式的基础语法:
 *   Java8中引入了一个新的操作符 "->"
 *   该操作符称为 箭头操作符 或 Lambda操作符
 *   箭头操作符将 Lambda 表达式拆分成两部分:
 *
 *   左侧:Lambda 表达式的参数列表
 *   右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
 *
 * Lambda 表达式需要“函数式接口”的支持
 *   函数式接口:接口中只有一个抽象方法的接口, 称为函数式接口
 *   可以使用注解 @FunctionalInterface 修饰, 可以检查是否是函数式接口
 */
public class MyTest2 {

    /**
     * 语法格式一:无参数,无返回值
     *   () -> System.out.println("Hello World!!!");
     */
    @Test
    public void test1() {
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello World!!!");
            }
        };
        r1.run();

        System.out.println("---------------------------");

        Runnable r2 = () -> System.out.println("Hello World!!!");
        r2.run();
    }

}

package com.szh.java8;

import org.junit.Test;

import java.util.Comparator;
import java.util.function.Consumer;

/**
 * Lambda 表达式的基础语法:
 *   Java8中引入了一个新的操作符 "->"
 *   该操作符称为 箭头操作符 或 Lambda操作符
 *   箭头操作符将 Lambda 表达式拆分成两部分:
 *
 *   左侧:Lambda 表达式的参数列表
 *   右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
 *
 * Lambda 表达式需要“函数式接口”的支持
 *   函数式接口:接口中只有一个抽象方法的接口, 称为函数式接口
 *   可以使用注解 @FunctionalInterface 修饰, 可以检查是否是函数式接口
 */
public class MyTest2 {

    /**
     * 语法格式二:有一个参数,无返回值
     *   (x) -> System.out.println(x)
     *   此语法格式中小括号可以省略不写,等价于
     *   x -> System.out.println(x)
     */
    @Test
    public void test2() {
        Consumer<String> consumer = (str) -> System.out.println(str);
        consumer.accept("Lambda表达式真好用....");
    }

}

package com.szh.java8;

import org.junit.Test;

import java.util.Comparator;
import java.util.function.Consumer;

/**
 * Lambda 表达式的基础语法:
 *   Java8中引入了一个新的操作符 "->"
 *   该操作符称为 箭头操作符 或 Lambda操作符
 *   箭头操作符将 Lambda 表达式拆分成两部分:
 *
 *   左侧:Lambda 表达式的参数列表
 *   右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
 *
 * Lambda 表达式需要“函数式接口”的支持
 *   函数式接口:接口中只有一个抽象方法的接口, 称为函数式接口
 *   可以使用注解 @FunctionalInterface 修饰, 可以检查是否是函数式接口
 */
public class MyTest2 {

    /**
     * 语法格式三:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
     */
    @Test
    public void test3() {
        Comparator<Integer> comparator = (x,y) -> {
            System.out.println("函数式接口....");
            return Integer.compare(x,y);
        };
    }

}
package com.szh.java8;

import org.junit.Test;

import java.util.Comparator;
import java.util.function.Consumer;

/**
 * Lambda 表达式的基础语法:
 *   Java8中引入了一个新的操作符 "->"
 *   该操作符称为 箭头操作符 或 Lambda操作符
 *   箭头操作符将 Lambda 表达式拆分成两部分:
 *
 *   左侧:Lambda 表达式的参数列表
 *   右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
 *
 * Lambda 表达式需要“函数式接口”的支持
 *   函数式接口:接口中只有一个抽象方法的接口, 称为函数式接口
 *   可以使用注解 @FunctionalInterface 修饰, 可以检查是否是函数式接口
 */
public class MyTest2 {

    /**
     * 语法格式四:若 Lambda 体中只有一条语句,
     *           则 return 和 大括号都可以省略不写
     * Lambda 表达式的参数列表的数据类型可以省略不写,
     * 因为JVM编译器通过上下文推断出,数据类型,即 “类型推断”
     */
    @Test
    public void test4() {
        Comparator<Integer> comparator = (x,y) -> Integer.compare(x,y);
    }

}

上述 Lambda 表达式中的参数类型都是由编译器推断得出的。Lambda 表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台
推断出了参数的类型。Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的 “类型推断”。

4.自定义函数式接口

只包含一个抽象方法的接口,称为 函 数 式 接 口。

你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明)

我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。

就像Runnable接口一样,它就是一个典型的函数式接口。

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface {@code Runnable} is used
     * to create a thread, starting the thread causes the object's
     * {@code run} method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method {@code run} is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

那么我们肯定也可以自定义函数式接口了,首先是没有泛型的自定义函数式接口。

package com.szh.java8.two;

/**
 *
 */
@FunctionalInterface
public interface MyFunction {

    public String getValue(String str);
}
package com.szh.java8.two;

/**
 *
 */
public class TestLambda {

    private static String strHandler(String str,MyFunction mf) {
        return mf.getValue(str);
    }

    public static void main(String[] args) {
        //去除首尾空格
        String trimStr = strHandler("\t\t\t  张起灵-小哥   ",(str) -> str.trim());
        System.out.println(trimStr);

        //转为大写
        String upperStr = strHandler("hello world",str -> str.toUpperCase());
        System.out.println(upperStr);

        //部分截取
        String newStr = strHandler("学Java的冷少",(str) -> str.substring(0,5));
        System.out.println(newStr);
    }
}

下面再来看一个带泛型的函数式接口。

package com.szh.java8.three;

/**
 *
 */
@FunctionalInterface
public interface MyFunction2<T,R> {

    public R getValue(T t1,T t2);
}
package com.szh.java8.three;

import com.szh.java8.two.MyFunction;

/**
 *
 */
public class TestLambda {

    private static void operation(Long l1,Long l2,MyFunction2<Long,Long> mf) {
        System.out.println(mf.getValue(l1,l2));
    }

    public static void main(String[] args) {
        //和
        operation(100L,200L,(x,y) -> x + y);

        //积
        operation(300L,500L,(x,y) -> x * y);
    }
}

作为参数传递 Lambda 表达式:为了将 Lambda 表达式作为参数传递 ,接收 Lambda 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口的类型。

以上就是深入理解Java8新特性之Lambda表达式的基本语法和自定义函数式接口的详细内容,更多关于Java Lambda表达式的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java中Lambda表达式的进化之路详解

    目录 Lambda表达式的进化之路 为什么要使用Lambda表达式 Lambda表达式的注意点 下面是Lambda表达式的实现过程 1.最开始使用的是定义外部实现类来完成接口 2.开始使用静态内部类来实现 3.使用局部内部类使用 4.使用匿名内部类实现接口 5..最后使用Lambda表达式实现函数式接口 总结 Lambda表达式的进化之路 为什么要使用Lambda表达式 可以简洁代码,提高代码的可读性 可以避免匿名内部类定义过多导致逻辑紊乱 在原先实现接口抽象方法的时候,需要通过定义一个实现接口

  • Java中Lambda表达式基础及使用

    目录 一.举例说明 1.无参无返回 1.1 定义一个接口 1.2接口实现类 1.3 测试类 2.有参无返回代码示例 3.有参有返回 二.简单事项 1.省略模式 2.注意事项 三.Lambda表达式和匿名内部类的区别 1.所需类型不同: 2.使用限制不同: 3.实现原理不同: 标准格式: 三要素:形式参数 箭头 代码块 格式:(形式参数)->{代码块} 形式参数:如果多个参数用逗号隔开,无参留空 ->:英文中划线和大于号组成 代码块:具体要做的事 使用前提: 有一个接口 接口中有且仅有一个抽象方

  • 吊打Java面试官之Lambda表达式 Stream API

    目录 一.jdk8新特性简介 二.Lambda表达式 简单理解一下Lambda表达式 Lambda表达式的使用 三.函数式接口 1.什么是函数式接口 2.如何理解函数式接口 3.Java内置四大核心函数式接口 四.方法引用与构造器引用 方法引用 构造器引用和数组引用 五.Stream API 1.Stream API的说明 2.为什么要使用Stream API 3.创建Stream的四种方式 4.Stream的中间操作及其测试 5.Stream的终止操作及其测试 六.Optional类的使用 O

  • 一文带你掌握Java8中Lambda表达式 函数式接口及方法构造器数组的引用

    目录 函数式接口概述 函数式接口示例 1.Runnable接口 2.自定义函数式接口 3.作为参数传递 Lambda 表达式 内置函数式接口 Lambda简述 Lambda语法 方法引用 构造器引用 数组引用 函数式接口概述 只包含一个抽象方法的接口,称为函数式接口. 可以通过 Lambda 表达式来创建该接口的对象. 可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口.同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口.

  • java Lambda表达式的使用心得

    目录 Lambda表达式的心得 Lambda表达式法 传统方法 使用Lambda表达式 你首先要知道的 Lambda表达式的技巧 Lambda表达式只能用来简化仅包含一个public方法的接口的创建 双冒号表达形式 Lambda表达式的心得 如题,因为博主也是最近才接触到Lambda表达式的(PS 在这里汗颜一会).我并不会讲解它的原理,诚然任何一件事物如果理解原理的话,使用它必将更加容易.但博主在学习的时候,大多数时候都是学会怎么用,然后在细究原理.就像你骑自行车之前,难道首先还要研究自行车的

  • Java语法中Lambda表达式无法抛出异常的解决

    目录 Lambda表达式无法抛出异常 1.Demo 例子 2.编译通过 lambda表达式异常应该如何处理 我们看一个例子 Lambda表达式无法抛出异常 1.Demo 例子 错误提示 - Unhandled exception: java.io.IOException; public static void main(String[] args) throws IOException{ Stream.of("a", "b", "c").forE

  • Java中使用Lambda表达式和函数编程示例

    目录 1.简单介绍 2.Lambdas和Scopes 3.Lambdas与局部变量 4.Lambda体与局部变量 5.Lambdas和'This'和'Super'关键字 6.Lambdas和Exceptions 7.预定义的功能接口 1.简单介绍 第一个示例演示变量声明上下文中的lambda.它将lambda()->{System.out.println("running"):}分配给可运行接口类型的变量r. 第二个示例类似,但演示了赋值上下文中的lambda(到先前声明的变量r

  • Java中Lambda表达式的使用详解

    目录 理解函数式接口以及 Lambda表达式的发展过程 Lambda表达式及语法 一起来看看具体的使用 你需要注意什么 Lambda的实际运用 1.对集合排序 2.遍历集合 3.遍历集合(带条件) 4.代替 Runnable,开启一个线程 理解函数式接口以及 Lambda表达式的发展过程 任何接口,只包含唯一一个抽象方法,就是函数式接口 /** * lambdab表达式的发展 */ public class TestLambda1 { //3.静态内部类 static class Like2 i

  • 深入理解Java8新特性之Lambda表达式的基本语法和自定义函数式接口

    1.写在前面 目前我们学习Java主要用到的应该就是Java8了,或者说大部分企业当前使用的也是Java8.那么既然Java8的应用如此之广泛,一定有一些亮点所在: Lambda 表达式 函数式接口 方法引用与构造器引用 Stream API 接口中的默认方法与静态方法 新时间日期API 其他新特性 速度更快.代码更少(增加了新的语法 Lambda 表达式).强大的 Stream API.便于并行.最大化减少空指针异常 Optional. 2.为什么要使用Lambda表达式? Lambda 是一

  • Java8新特性:Lambda表达式之方法引用详解

    1.方法引用简述 方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法.方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文.计算时,方法引用会创建函数式接口的一个实例. 当Lambda表达式中只是执行一个方法调用时,不用Lambda表达式,直接通过方法引用的形式可读性更高一些.方法引用是一种更简洁易懂的Lambda表达式. Lambda表达式全文详情地址:http://blog.csdn.net/sun_promise/article/details/

  • Java8新特性之Lambda表达式的使用

    1. lambda表达式介绍 lambda表达式是Java8提供的新特性之一,也可以称之为闭包:它支持Java能够进行简单的函数式编程,也就是说可以把一个匿名函数作为一个方法的参数进行传递:其格式分为三部分,第一部分为入参列表,第二部由->固定组成,第三部分为方法体: public class LambdaTest { public static void main(String[] args) { // 使用lambda表达式创建线程 Thread thread = new Thread(()

  • 简单易懂的java8新特性之lambda表达式知识总结

    一.概念 从本质上来说,它就是一个匿名函数,可以用来直接实现接口中的方法,从而简化代码.但是Lambda有一个限制,不能实现接口中的所有方法,所以Lambda表达式只能用于有且仅有一个必须需要实现的方法接口,这里需要注意必须需要实现这六个字. public interface Printer { //有一个需要实现的方法,可以使用Lambda表达式 void print(); } public interface Printer { //有一个需要实现的方法,可以使用Lambda表达式 void

  • Java8新特性之Lambda表达式浅析

    说到java 8,首先会想到lambda(闭包)以及虚拟扩展方法(default method),这个特性早已经被各大技术网站炒得沸沸扬扬了,也是我们java 8系列开篇要讲的第一特性(JEP126 http://openjdk.java.net/jeps/126),jdk8的一些库已经应用了lambda表达式重新设计了,理解他对学习java 8新特性有着重要的意义. 一.函数式接口 函数式接口(functional interface 也叫功能性接口,其实是同一个东西).简单来说,函数式接口是

  • 深入理解Java8新特性之Stream API的创建方式和中间操作步骤

    目录 1.什么是StreamAPI? 2.Stream API操作的三个步骤 2.1 创建Stream 2.2 中间操作 2.2.1 中间操作之筛选与切片 2.2.2 中间操作之映射 2.2.3 中间操作之排序 1.什么是StreamAPI? Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 m Stream API (java.util.stream.*) . Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复

  • 深入浅析JDK8新特性之Lambda表达式

    第一次是接触Lambda表达式是在TypeScript中(JavaScript的超集中),当时是为了让TypeScript的this方法外而不是本方法内所使用的.使用过后突然想到Lambda不是JDK8的重量级新特性么?于是感觉查阅相关资料并记录下来: 一. 行为参数化 行为参数化简单的说就是函数的主体仅包含模板类通用代码,而一些会随着业务场景而变化的逻辑则以参数的形式传递到函数之中,采用行为参数化可以让程序更加的通用,以应对频繁变更的需求. 考虑一个业务场景,假设我们需要通过程序对苹果进行筛选

  • 浅析C++11新特性的Lambda表达式

    lambda简介 熟悉Python的程序员应该对lambda不陌生.简单来说,lambda就是一个匿名的可调用代码块.在C++11新标准中,lambda具有如下格式: [capture list] (parameter list) -> return type { function body } 可以看到,他有四个组成部分: 1.capture list: 捕获列表 2.parameter list: 参数列表 3.return type: 返回类型 4.function body: 执行代码

  • 深入理解Java8新特性之Stream API的终止操作步骤

    目录 1.写在前面 2.终止操作 2.1 终止操作之查找与匹配 2.2 终止操作之归约与收集 1.写在前面 承接了上一篇文章(说完了Stream API的创建方式及中间操作):深入理解Java8新特性之Stream API的创建方式和中间操作步骤. 我们都知道Stream API完成的操作是需要三步的:创建Stream → 中间操作 → 终止操作.那么这篇文章就来说一下终止操作. 2.终止操作 终端操作会从流的流水线生成结果.其结果可以是任何不是流的值,例如:List.Integer,甚至是 v

  • 深入理解Java8新特性之Optional容器类的应用

    1.Optional容器类 Optional<T> 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念.并且可以避免空指针异常. 常用方法 : Optional.of(T t) : 创建一个 Optional 实例 Optional.empty() : 创建一个空的 Optional 实例 Optional.ofNullable(T t) : 若 t 不为 null,创建 Opti

随机推荐