Java8简单了解Lambda表达式与函数式接口

Java8被称作Java史上变化最大的一个版本。其中包含很多重要的新特性,最核心的就是增加了Lambda表达式和StreamAPI。这两者也可以结合在一起使用。首先来看下什么是Lambda表达式。

使用Lambda表达式不仅让代码变的简单、而且可读、最重要的是代码量也随之减少很多。然而,在某种程度上,这些功能在Scala等这些JVM语言里已经被广泛使用。

并不奇怪,Scala社区是难以置信的,因为许多Java 8里的内容看起来就像是从Scala里搬过来的。在某种程度上,Java 8的语法要比Scala的更详细但不是很清晰,但这并不能说明什么,如果可以,它可能会像Scala那样构建Lambda表达式。

一方面,如果Java继续围绕Lambda来发展和实现Scala都已经实现的功能,那么可能就不需要Scala了。另一方面,如果它只提供一些核心的功能,例如帮助匿名内部类,那么Scala和其他语言将会继续茁壮成长,并且有可能会凌驾于Java之上。其实这才是最好的结果,有竞争才有进步,其它语言继续发展和成长,并且无需担心是否会过时。

Lambda表达式,维基百科上的解释是一种用于表示匿名函数和闭包的运算符,感觉看到这个解释还是觉得很抽象,接下来我们看一个例子

public class SwingTest {
  public static void main(String[] args) {
    JFrame jFrame = new JFrame("My JFrame");
    JButton jButton = new JButton("My JButton");

    jButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        System.out.println("Button Pressed!");
      }
    }); 

    jFrame.add(jButton); jFrame.pack();
    jFrame.setVisible(true);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }
}

这是一段Swing编程中的代码,给Button绑定一个监听事件,当点击Button时会在控制台输出"ButtonPressed!"内容。这里使用了创建了一个匿名内部类的实例来绑定到监听器,这也是以往比较常规的代码组织形式。但是仔细看一下我们会发现,实际上我们真正关注的就是一个ActionEvent类型的参数e和向控制台输出的语句System.out.println("ButtonPressed!");。

如果将上段程序中以匿名内部类的方式创建接口实例的代码替换成Lambda表达式后,代码如下

public class SwingTest {

public static void main(String[] args) {
  JFrame jFrame = new JFrame("My JFrame");
  JButton jButton = new JButton("My JButton");

  jButton.addActionListener(e -> System.out.println("Button Pressed!"));

  jFrame.add(jButton);
  jFrame.pack();
  jFrame.setVisible(true);
  jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

关注最中间部分代码的变化,由原来的6行代码,现在1行就可以实现了。这就是Lambda表达式的一种简单形式。
可以看出Lambda表达式的语法是

(param1,param2,param3) -> {

//todo
}

这里参数的类型程序可以根据上下文进行推断,但是并不是所有的类型都可以推断出来,此时就需要我们显示的声明参数类型,当只有一个参数时小括号可以省略。当todo部分只有一行代码时,外边的大括号可以省略。如我们上面的示例

那么除了代码简洁了,Lambda表达式还给我们带来了什么变化吗?

我们回忆一下,在Java中,我们是否无法将函数作为参数传递给一个方法,也无法声明返回值是一个函数的方法。在Java8之前,答案是肯定的。

那么,在上面的例子中我们居然可以将一段代码逻辑作为参数传递给了监听器,告诉监听器事件触发时你可以这么做,而不再需要以匿名内部类的方式作为参数。这也是Java8带来的另一新特性:函数式编程。

支持函数式编程的语言有很多,在JavaScript中,把函数作为参数传递,或者返回值是一个函数的情况非常常见,JavaScript是一门非常常见的函数式语言。

Lambda为Java添加了缺失的函数式编程的特性,使我们能将函数当做一等公民看待。

在函数式编程语言中,Lambda表达式的类型是函数。而在Java中,Lambda表达式是对象,它们必须依附于一类特别的对象类型——函数式接口(FunctionalInterface)。

接下来我们看下函数式接口的定义:

如果一个接口中,有且只有一个抽象的方法(Object类中的方法不包括在内),那这个接口就可以被看做是函数式接口。

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

来看下Runnable接口的声明,在Java8后,Runnable接口多了一个FunctionalInterface注解,表示该接口是一个函数式接口。但是如果我们不添加FunctionalInterface注解的话,如果接口中有且只有一个抽象方法时,编译器也会把该接口当做函数式接口看待。

@FunctionalInterface
public interface MyInterface {
  void test();
  String toString();
}

MyInterface这也是一个函数式接口,因为toString()是Object类中的方法,只是在这里进行了复写,不会增加接口中抽象方法的数量。

(到这里额外提一下,Java8中,接口里面的方法不仅仅只能有抽象方法,也可以有具体实现了的方法,被称作默认方法(defaultmethod),这部分后面会具体介绍)

既然在Java中,Lambda表达式是对象。那么这个对象的类型是什么呢?我们再回顾下SwingTest程序,这里以匿名内部类的方式创建了一个ActionListener接口实例

jButton.addActionListener(new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent e) {
    System.out.println("Button Pressed!");
  }
}); 

使用Lambda表达式改进后

jButton.addActionListener(e -> System.out.println("Button Pressed!"));

也就是我们使用Lambda表达式创建了一个ActionListener接口的实例,再看下ActionListener接口的定义

public interface ActionListener extends EventListener {
  /**
   * Invoked when an action occurs.
   */
  public void actionPerformed(ActionEvent e);
}

只有一个抽象方法,虽然没添加FunctionalInterface注解,但是也符合函数式接口的定义,编译器会认为这是一个函数式接口。
所以,使用Lambda表达式可以创建函数式接口的实例。即Lambda表达式返回的是函数式接口类型。

实际上,函数式接口实例的创建可以有三种方式(参考自FunctionalInterface注解说明):

1.Lambda表达式
2.方法引用
3.构造方法引用

总结

以上就是本文关于Java8简单了解Lambda表达式与函数式接口的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出!

(0)

相关推荐

  • Lambda表达式和Java集合框架

    本文github地址 Java8为容器新增一些有用的方法,这些方法有些是为完善原有功能,有些是为引入函数式编程(Lambda表达式),学习和使用这些方法有助于我们写出更加简洁有效的代码.本文分别以ArrayList和HashMap为例,讲解Java8集合框架(Java Collections Framework)中新加入方法的使用. 前言 我们先从最熟悉的Java集合框架(Java Collections Framework, JCF)开始说起. 为引入Lambda表达式,Java8新增了jav

  • 浅析Java8新特性Lambda表达式和函数式接口

    什么是Lambda表达式,java8为什么使用Lambda表达式? "Lambda 表达式"(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数.我们可以把 Lambda表达式理解为是 一段可以传递的代码.最直观的是使用Lambda表达式之后不用再写大量的匿名内部类,简化代码,提高了代码的可读性. // 启动一个线程,不使用Lambda

  • Java8新特性之lambda的作用_动力节点Java学院整理

    我们期待了很久lambda为java带来闭包的概念,但是如果我们不在集合中使用它的话,就损失了很大价值.现有接口迁移成为lambda风格的问题已经通过default methods解决了,在这篇文章将深入解析Java集合里面的批量数据操作(bulk operation),解开lambda最强作用的神秘面纱. 1.关于JSR335 JSR是Java Specification Requests的缩写,意思是Java 规范请求,Java 8 版本的主要改进是 Lambda 项目(JSR 335),其

  • Java8新特性Lambda表达式的一些复杂用法总结

    简介 lambda表达式是JAVA8中提供的一种新的特性,它支持Java也能进行简单的"函数式编程". 它是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数. 本文将介绍关于Java8 Lambda表达式的一些复杂用法,分享出来供大家参考学习,下面来一起看看详细的介绍: 复杂用法实例 传入数组ids,在list<Obj>上操作,找出Obj中id想匹配的,并且按

  • Java8 新特性Lambda表达式实例详解

    Java8 新特性Lambda表达式实例详解 在介绍Lambda表达式之前,我们先来看只有单个方法的Interface(通常我们称之为回调接口): public interface OnClickListener { void onClick(View v); } 我们是这样使用它的: button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { v.setText("

  • Java8深入学习系列(一)lambda表达式介绍

    前言 最近在学习java8,所以接下来会给大家介绍一系列的Java8学习内容,那么让我们先从lambda表达式开始. 众所周知从java8出现以来lambda是最重要的特性之一,它可以让我们用简洁流畅的代码完成一个功能. 很长一段时间java被吐槽是冗余和缺乏函数式编程能力的语言,随着函数式编程的流行java8种也引入了 这种编程风格.在此之前我们都在写匿名内部类干这些事,但有时候这不是好的做法,本文中将介绍和使用lambda, 带你体验函数式编程的魔力. 什么是lambda? lambda表达

  • Java的lambda表达式实现解析

    Java8引入了lambda表达式.lambda表达式并不是新功能,只是为了方便代码编写的语法糖. 但,即便是在其他语言已经司空见惯的lambda表达式,如果在Java中要支持它,还需要考虑各种向下兼容的问题. 简单的说,Java的lambda表达式支持,大约需要考虑2个方面 需要支持lambda语法,以替代原有的方法匿名类 需要考虑已有JDK中,如何增加新操作以支持lambda表达式 对于第一点的回答是FuntionalInterface的Annotation,第二点的回答是default方法

  • 使用Java 8中的Lambda表达式实现工厂模式

    前言 工厂模式是面向对象设计模式中大家最为熟知的设计模式之一.传统的实现方式大家都在熟悉不过了,今天将向大家介绍使用Java8 Lambda 表达式更加优雅的实现工厂模式. 封面 工厂模式在java中最常用的设计模式之一,它提供了一种很好的实例化对象的方法,是替代new操作的一种模式常用的方式.工厂设计模式可以让你实例化对象的逻辑不用暴露给客户端. 在下面的文章中我将给出使用传统的代码实现工厂模式的一个例子,然后再使用 Java8 Lambada 方式重新实现 一个例子 首先我将创建一个 Sha

  • Java8简单了解Lambda表达式与函数式接口

    Java8被称作Java史上变化最大的一个版本.其中包含很多重要的新特性,最核心的就是增加了Lambda表达式和StreamAPI.这两者也可以结合在一起使用.首先来看下什么是Lambda表达式. 使用Lambda表达式不仅让代码变的简单.而且可读.最重要的是代码量也随之减少很多.然而,在某种程度上,这些功能在Scala等这些JVM语言里已经被广泛使用. 并不奇怪,Scala社区是难以置信的,因为许多Java 8里的内容看起来就像是从Scala里搬过来的.在某种程度上,Java 8的语法要比Sc

  • Java特性 Lambda 表达式和函数式接口

    目录 Java Lambda表达式 起源&概念 语法 简单例子 Lambda简化Runnable例子 代码分析 自定义接口实现lambda 函数式接口 概念 备注 格式 @FunctionalInterface注解 自定义函数式接口 Java Lambda表达式 为方便使用Java函数式接口,一定要搞清楚Java的Lambda表达式怎么书写.同时Java的Lambda不是那么通俗易懂,所以一定得学明白,不然其实后面涉及到Lambda的代码部分会变得晦涩难懂.而且掌握Lambda表达式可以让你写出

  • Java Lambda表达式和函数式接口实例分析

    本文实例讲述了Java Lambda表达式和函数式接口.分享给大家供大家参考,具体如下: 一 点睛 Lambda表达式的类型,也称为"目标类型",Lambda表达式的目标类型必须是函数式接口.函数式接口代表只包含一个抽象方法的接口.函数式接口可以包含多个默认方法.类方法,但只能声明一个抽象方法. 如果采用匿名内部类语法来创建函数式接口的实例,只要实现一个抽象方法即可,在这种情况下即可采用Lambda表达式来创建对象,该表达式创建出来的对象的目标类型就是这个函数式接口. Java 8专门

  • Java8新特性:lambda表达式总结

    一.Lambda 表达式的基础语法 Lambda 表达式的基础语法:Java8中引入了一个新的操作符 "->" 该操作符称为箭头操作符或 Lambda 操作符箭头操作符将 Lambda 表达式拆分成两部分: 左侧:Lambda 表达式的参数列表 右侧:Lambda 表达式中所需执行的功能,即 Lambda 体 语法格式一:无参数,无返回值 () -> System.out.println("Hello Lambda!"); 语法格式二:有一个参数,并且无

  • Java8中的 Lambda表达式教程

     1. 什么是λ表达式 λ表达式本质上是一个匿名方法.让我们来看下面这个例子: public int add(int x, int y) { return x + y; } 转成λ表达式后是这个样子: (int x, int y) -> x + y; 参数类型也可以省略,Java编译器会根据上下文推断出来: (x, y) -> x + y; //返回两数之和 或者 (x, y) -> { return x + y; } //显式指明返回值 可见λ表达式有三部分组成:参数列表,箭头(-&g

  • Java8中的lambda表达式入门教程

    1.基本介绍 lambda表达式,即带有参数的表达式,为了更清晰地理解lambda表达式,先上代码: 1.1 两种方式的对比 1.1.1 方式1-匿名内部类 class Student{ private String name; private Double score; public Student(String name, Double score) { this.name = name; this.score = score; } public String getName() { ret

  • Java8如何使用Lambda表达式简化代码详解

    系统环境: Java JDK 版本:1.8 参考地址: Java 8 Lambda 表达式 Jdk 8 新特性 04 方法引用与构造器引用 Java 8 新特性:Lambda 表达式之方法引用 一.Lambda 表达式简介 1.什么是 Lambda 表达式 Lambda 表达式是在 JDK 8 中引入的一个新特性,可用于取代大部分的匿名内部类.使用 Lambda 表达式可以完成用少量的代码实现复杂的功能,极大的简化代码代码量和代码结构.同时,JDK 中也增加了大量的内置函数式接口供我们使用,使得

  • 详解Java8中的lambda表达式、::符号和Optional类

    Java8中的lambda表达式.::符号和Optional类 0. 函数式编程 函数式编程(Functional Programming)属于编程范式(Programming Paradigm)中的用语,此外还有命令式编程(Imperative Programing)等,有兴趣的同学可以自行了解,我们这里大概解释一下函数式编程,在函数式编程中,输入一旦确定了,输出都确定了,函数调用的结果只依赖于传入的输入变量和内部逻辑,不依赖于外部,这样的写出的函数没有副作用.举个例子: public cla

随机推荐