• 1.1 为什么要使用lambda 表达式


    第1章 lambda 表达式

    1.1 为什么要使用lambda 表达式

    1.2 lambda 表达式的语法

    1.3 函数式接口

    1.4 方法引用

    1.5 构造器引用

    1.6 变量作用域

    1.7 默认方法

    1.8 接口中的静态方法

    练习

    Java 作为一门面向对象的编程语言诞生于20 世纪90 年代,在当时,面向对象编程是软件开发的主流模式。在面向对象编程出现之前,也曾诞生过像Lisp 和Scheme 这样的函数式编程语言,但它们只活跃于学术圈中。最近,由于在并发和事件驱动(或者称“互动”)编程中的优势,函数式编程又逐渐变得重要起来。这并不意味着面向对象编程不好,相反,最终的趋势是将面向对象编程和函数式编程结合起来。即使你对并发等功能不感兴趣,函数式编程也会给你带来帮助。例如,如果语言有了非常方便的函数表达式语法,集合API 就会变得异常强大。

    Java 8 主要是在原来面向对象的基础上增加了函数式编程的能力。在本章中,你将学习基本的语法。下一章将会向你介绍如何利用这些语法来使用Java 集合类,第3章将介绍如何构建自己的函数式API。

    本章的要点包括:

    一个lambda 表达式是一个带有参数的代码块。

    当你想要代码块在以后某个时间点执行时,可以使用lambda 表达式。

    lambda 表达式可以被转换为函数式接口。

    lambda 表达式可以在闭包作用域中有效地访问final 变量。

    方法和构造器引用可以引用方法或构造器,但无须调用它们。

    你现在可以向接口添加默认(default)和静态(static)方法来提供具体的实现。

    你必须解决接口中多个默认方法之间的冲突。

    1.1 为什么要使用lambda 表达式

    “lambda 表达式”是一段可以传递的代码,因此它可以被执行一次或多次。在学习语法(甚至包括一些奇怪的术语)之前,我们先回顾一下之前在Java 中一直使用的相似的代码块。

    当我们要在另一个独立线程中执行一些逻辑时,通常会将代码放在一个实现Runnable 接口的类的run 方法中,如下所示:
     

    1. class Worker implements Runnable {  
    2. public void run() {  
    3. for (int i = 0; i < 1000; i++)  
    4. doWork();  
    5. }  
    6. ...  

    然后,当我们希望执行这段代码时,会构造一个Worker 类的实例。然后将该实例提交到一个线程池中,或者简单点,直接启动一个新的线程:
     

    1. Worker w = new Worker();  
    2. new Thread(w).start(); 

    这段代码的关键在于,run 方法中包含了你希望在另一个线程中执行的代码。我们考虑一下用一个自定义的比较器来进行排序。如果你希望按照字符串的长度而不是默认的字典顺序来排序,那么你可以将一个Comparator 对象传递给sort 方法:
     

    1. class LengthComparator implements Comparator<String> {  
    2. public int compare(String first, String second) {  
    3. return Integer.compare(first.length(), second.length());  
    4. }  
    5. }  
    6. Arrays.sort(strings, new LengthComparator()); 

    sort 方法会一直调用compare 方法,对顺序不对的元素进行重新排序,直到数组完全有序为止。你给sort 方法传递了一段需要比较元素的代码片段,而该代码会被整合到排序逻辑中,而你可能并不关心如何在那里实现。

    注意:如果x=y,那么Integer.compare(x,y)会返回0;如果x<y,则它会返回一个负数;而如果x>y,则它会返回一个正数。这个静态方法已经被添加到Java 7中(请参考第9 章)。还要注意,不应该使用x-y 来比较x 和y 的大小,因为对于大的、符号相反的操作数,这种计算有可能会产生溢出。

    按钮回调是另外一个会延迟执行的例子。你将回调操作放到一个实现了监听器接口的类的某个方法中,然后构造一个实例,并将实例注册到按钮上。在这种情况下,许多开发人员都会使用“匿名类的匿名实例”的方法:
     

    1. button.setOnAction(new EventHandler<ActionEvent>() {  
    2. public void handle(ActionEvent event) {  
    3. System.out.println("Thanks for clicking!");  
    4. }  
    5. }); 

    这里的关键是代码处于handle 方法中。该代码会在按钮被点击时执行。

    注意:由于Java 8 将JavaFX 作为Swing GUI 的下一任继承者,我会在这些示例中使用JavaFX(请参考第4 章来了解更多关于JavaFX 的信息)。当然,细节并不重要,因为不管是Swing、JavaFX 还是Android,你都需要为按钮添加一些代码,以使它们在按钮被点击时可以执行。

    在所有三个例子中,你会看到相同的方式。一段代码会被传递给其他调用者——也许是一个线程池、一个排序方法,或者是一个按钮。这段代码会在稍后被调用。

    到现在为止,在Java 中向其他代码传递一段代码并不是很容易。你不可能将代码块到处传递。由于Java 是一个面向对象的语言,因此你不得不构建一个属于某个类的对象,由它的某个方法来包含所需的代码。

    在其他一些语言中可以直接使用代码块。在很长一段时间里,Java 设计者们都拒绝加入这一特性。毕竟,Java 的一大优势在于它的简单和一致性。如果一个语言包含了所有可以略微简化代码的特性,那么它就会变得不可维护。但是,在其他那些语言中,并不只是产生线程或者注册按钮点击事件的代码变得更简单了,它们大量的API 都是更简单、更一致、更强大的。虽然我们已经通过类、对象的方式在Java 中实现了相似的API和功能,但是这些API 使用起来并不让人感到轻松和愉快。

    最近的一段时间,争论的问题已经不再是Java 是否要变成一门函数式编程语言,而是如何实现这种改变了。在设计出一个适合Java 的解决办法之前已经进行了多年的实验。在下一节中,你将会看到如何在Java 8 中使用代码块。

  • 相关阅读:
    七。进度管理
    六。质量管理
    五。项目范围管理
    四。项目整体管理
    三。项目立项管理
    二。项目的一般只知识
    一。项目管理的管理领域
    8.BGP
    英语词汇基础
    vim中输入tab符
  • 原文地址:https://www.cnblogs.com/songyz/p/6180278.html
Copyright © 2020-2023  润新知