文章目录

  • 1. Lambda表达式
    • 1.1 Lambda表达式语法
    • 1.2 Lambda表达式示例
    • 1.3 说明:函数式接口
  • 2. 方法的默认实现和静态方法
  • 3. 方法引用
    • 3.1 方法引用示例
  • 4. 注解(Annotation)
  • 5. 类型推测
  • 6. 新增Optional类
  • 7. 新增Stream类
  • 8. 调用JavaScript
  • 9. Base64

1. Lambda表达式

Lambda表达式是一个匿名函数(指的是没有函数名的函数),它基于数学中的λ演算得名,直接对应于其中的Lambda抽象。


1.1 Lambda表达式语法

Lambda表达式允许把函数作为一个方法的参数。Lambda表达式的基本语法如下所示:

(parameters) -> expression
// 或者
(parameters) -> { expression }

1.2 Lambda表达式示例

Arrays.asList(1, 3, 5, 7, 9).forEach(item -> System.out.println(item));

运行结果:

以上这种写法中,i的类型由编译器推测出来的,当然,也可以显式地指定类型,如下例所示:

Arrays.asList(1, 3, 5, 7, 9).forEach((Integer item) -> System.out.println(item));

Java8以前,Java语言通过匿名函数的方法来代替Lambda表达式。

对于列表的排序,如果列表里面存放的是自定义的类,那么通常需要指定自定义的排序方法,传统的写法如下所示:

Test.java

package com.tian;import java.util.Arrays;
import java.util.Comparator;/*** @author CodeJiao*/
class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}public class Test {public static void main(String[] args) {Person[] peoples = {new Person("Jack", 20), new Person("Rose", 18)};// 自定义排序方法, 通过年龄进行排序Arrays.sort(peoples, new Comparator<Person>() {@Overridepublic int compare(Person person1, Person person2) {// 根据年龄升序排序return person1.getAge() - person2.getAge();}});for (Person people : peoples) {System.out.println(people);}}
}

运行结果:


采用Lambda表达式后,写法如下所示:

        // 自定义排序方法, 通过年龄进行排序Arrays.sort(peoples, (person1, person2) -> {// 根据年龄升序排序return person1.getAge() - person2.getAge();});

或者

        // 自定义排序方法, 通过年龄进行排序Arrays.sort(peoples, (Person person1, Person person2) -> {// 根据年龄升序排序return person1.getAge() - person2.getAge();});

1.3 说明:函数式接口

Lambda表达式是通过函数式接口(只有一个方法的普通接口)来实现的。函数式接口可以被隐式地转换为Lambda表达式。为了与普通的接口区分开(普通接口中可能会有多个方法),JDK1.8新增加了一种特殊的注解@FunctionalInterface。下面给出一个函数式接口的定义:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}

2. 方法的默认实现和静态方法

JDK1.8通过使用关键字default可以给接口中的方法添加默认实现
此外,接口中还可以定义静态方法,示例代码如下所示:

public interface Test {void method1();default void method2() {System.out.println("我是接口的默认实现方法");}static void method3() {System.out.println("我是接口中的静态方法");}
}

那么,为什么要引入接口中方法的默认实现呢?

这样做的最重要的一个目的就是为了实现接口升级。在原有的设计中,如果想要升级接口,例如给接口中添加一个新的方法,那么会导致所有实现这个接口的类都需要被修改,这给 Java语言已有的一些框架进行升级带来了很大的麻烦。如果接口能支持默认方法的实现,那么可以给这些类库的升级带来许多便利。例如,为了支持Lambda表达式,Collection中引入了foreach方法,可以通过这个语法增加默认的实现,从而降低了对这个接口进行升级的代价,不需要所有实现这个接口的类进行修改。


3. 方法引用

方法引用指的是可以直接引用Java类或对象的方法。它可以被看成是一种更加简洁易懂的Lambda表达式,使用方法引用后,上例中的排序代码就可以使用下面更加简洁的方式来编写:

原来:

        // 自定义排序方法, 通过年龄进行排序Arrays.sort(peoples, (person1, person2) -> {// 根据年龄升序排序return person1.getAge() - person2.getAge();});

现在:

        // 自定义排序方法, 通过年龄进行排序Arrays.sort(peoples, Comparator.comparing(Person::getAge));

方法引用共有下面4种形式:

  • 引用构造方法:ClassName::new
  • 引用类静态方法:ClassName::methodName
  • 引用特定类的任意对象方法:ClassName::methodName
  • 引用某个对象的方法:instanceName::methodName

3.1 方法引用示例

Test.java

package com.tian;import java.util.Arrays;
import java.util.Comparator;
import java.util.function.Supplier;/*** @author CodeJiao*/
class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public static Person getInstance(final Supplier<Person> supplier) {return supplier.get();}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public static int compareByAge(Person a, Person b) {return b.age - a.age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}class CompareProvider {public int compareByAge(Person a, Person b) {return a.getAge() - b.getAge();}
}public class Test {public static void main(String[] args) {// 引用构造方法Person p1 = Person.getInstance(Person::new);p1.setAge(22);System.out.println("测试引用构造方法:" + p1.getAge());Person[] peoples = {new Person("Jack", 20), new Person("Rose", 18)};// 引用特定类的任意对象方法Arrays.sort(peoples, Comparator.comparing(Person::getAge));System.out.println("测试引用特定类的任意对象方法:");for (Person people : peoples) {System.out.println(people);}// 引用静态方法Arrays.sort(peoples, Person::compareByAge);System.out.println("测试引用静态方法:");for (Person people : peoples) {System.out.println(people);}// 引用某个对象的方法Arrays.sort(peoples, new CompareProvider()::compareByAge);System.out.println("测试引用某个对象的方法:");for (Person people : peoples) {System.out.println(people);}}
}

运行结果:


4. 注解(Annotation)

  • 1)JDK1.5中引入了注解机制,注解为开发人员在代码中添加信息提供了一种形式化的方法,它使得开发人员可以在某个时刻方便地使用这些数据(通过解析注解来使用这些数据)。注解的语法比较简单,除了@符号的使用以外,它基本上与Java语言的语法一致,Java语言内置了三种注解方式,它们分别是@Override(表示当前方法是覆盖父类的方法)、@Deprecated(表示当前元素是不赞成使用的)、@SuppressWarnings(表示关闭一些不当的编译器警告信息)。需要注意的是,它们都定义在 java.lang 包中。
  • 2) JDK1.8对注解进行了扩展。使得注解被使用的范围更广,例如可以给局部变量、泛型、方法异常等提供注解。

5. 类型推测

JDK1.8加强了类型推测机制,这种机制可以使得代码更为简洁,假如有如下类的定义。

在调用的时候,可以使用下面的代码:

在 Java 7的时候,这种写法将会产生编译错误,Java 7中的正确写法如下所示:
同理,在调用cons方法的时候的写法为:

Java 7 的时候需要显式地指定类型:List.cons(5,List.<Integer>nil());


6. 新增Optional类

在使用Java语言进行编程的时候,经常需要使用大量的代码来处理空指针异常,而这种操作往往会降低程序的可读性。JDK1.8引入了Optional类来处理空指针的情况,从而增强了代码的可读性,下面给出一个简单的例子:

示例代码:

package com.tian;import java.util.Optional;public class Test1 {public static void main(String[] args) {Optional<String> s1 = Optional.of("Hello");// 判断是否有值if (s1.isPresent()) {System.out.println(s1.get());}Optional<String> s2 = Optional.ofNullable(null);// 判断是否有值if (s2.isPresent()) {System.out.println(s2.get());}}
}

运行结果:


7. 新增Stream类

JDK1.8 新增加了Stream类,从而把函数式编程的风格引入到Java语言中,StreamAPI提供了非常强大的功能,使用Stream后,可以写出更加强大、更加简洁的代码(例如可以代替循环控制语句)。示例代码如下所示:

package com.tian;import java.util.*;
import java.util.stream.Collectors;class Student {private String name;private Integer age;public Student(String name, Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public Integer getAge() {return age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}public class Test2 {public static void main(String[] args) {ArrayList<Student> students = new ArrayList<>();// 初始化studentsstudents.add(new Student("张有余", 10));students.add(new Student("雷磊", 13));students.add(new Student("侯家领", 10));students.add(new Student("徐曦", 15));System.out.println("找出年龄为10的第一个学生");Optional<Student> s = students.stream().filter(student ->student.getAge() == 10).findFirst();if (s.isPresent()) {System.out.println(s.toString());}System.out.println("找出年龄为10的所有学生");List<Student> listStu = students.stream().filter(student -> student.getAge() == 10).collect(Collectors.toList());listStu.forEach(stu -> {System.out.println(stu.toString());});System.out.println("对学生按照年龄分组");Map<Integer, List<Student>> map = students.stream().collect(Collectors.groupingBy(Student::getAge));Iterator<Map.Entry<Integer, List<Student>>> iterator = map.entrySet().iterator();while (iterator.hasNext()) {Map.Entry<Integer, List<Student>> entry = iterator.next();Integer age = entry.getKey();System.out.println("age: " + age);List<Student> group = entry.getValue();for (Student student : group) {System.out.println(student.getName() + " ");}}}
}

运行结果:

此外,Stream类还提供了parallelmapreduce等方法,这些方法用于增加对原生类并发处理的能力,有兴趣的读者可以参考Java官方文档学习。


8. 调用JavaScript

JDK1.8 增加API使得通过Java 程序来调用 JavaScript 代码,使用示例如下所示:

package com.tian;import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;public class Test4 {public static void main(String[] args) throws ScriptException {ScriptEngineManager manager = new ScriptEngineManager();ScriptEngine engine = manager.getEngineByName("JavaScript");// 显示引擎名称System.out.println(engine.getClass().getName());// 调用JavaScript代码System.out.println(engine.eval("function f(){return 'Hello World'};" +"f();"));}
}

运行结果:


9. Base64

Base64编码是一种常见的字符编码,可用来作为电子邮件或 Web Service附件的传输编码。JDK1.8Base64编码添加到了标准类库中。示例代码如下所示:

package com.tian;import java.nio.charset.StandardCharsets;
import java.util.Base64;public class Test3 {public static void main(String[] args) {String str = "Hello World";String encodeStr = Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8));System.out.println(encodeStr);String decodeSr = new String(Base64.getDecoder().decode(encodeStr));System.out.println(decodeSr);}
}

运行结果:



Java8 新特性 -- Lambda表达式:函数式接口、方法的默认实现和静态方法、方法引用、注解、类型推测、Optional类、Stream类、调用JavaScript、Base64相关推荐

  1. Java8新特性----Lambda表达式详细探讨

    Java8新特性 Lambda表达式 入门演示 案例1 如何解决 cannot be cast to java.lang.Comparable问题? 案例2 优化方式一 : 策略设计模式 优化方式二: ...

  2. java8新特性lambda表达式、函数式编程、方法引用和接口默认方法以及内部类访问外部变量

    一提到java是一种什么语言? 大多数人肯定异口同声的说是一门面向对象的语言,这种观点从我们开始学java就已经根深蒂固了,但是学到java8新特性函数式编程的时候,我才知道java并不是纯面向对象的 ...

  3. Java8新特性——lambda表达式

    什么是lambda表达式? Lambda 表达式是Java 8 的新特性,是一种新的编程语法.lambda语义简洁明了,性能良好,是Java 8 的一大亮点.废话不多说,我们来看个例子. 从内部类到l ...

  4. java8新特性-lambda表达式入门学习

    定义 jdk8发布新特性中,lambda是一大亮点之一.lambda表达式能够简化我们对数据的操作,减少代码量,大大提升我们的开发效率.Lambda 表达式"(lambda expressi ...

  5. java compare 返回值_关于Java你不知道的那些事之Java8新特性[Lambda表达式和函数式接口]...

    前言 为什么要用Lambda表达式? Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码,将代码像数据一样传递,这样可以写出更简洁.更灵活的代码,作为一个更紧凑的代码风 ...

  6. java8新特性lambda表达式概述

    定义 ​ jdk8发布新特性中,lambda是一大亮点之一.lambda表达式能够简化我们对数据的操作,减少代码量,大大提升我们的开发效率.Lambda 表达式"(lambda expres ...

  7. 2020.10.20课堂笔记(java8新特性 lambda表达式)

    一.什么是Lambda? 我们知道,对于一个Java变量,我们可以赋给其一个"值". 如果你想把"一块代码"赋给一个Java变量,应该怎么做呢? 比如,我想把右 ...

  8. Java8 新特性lambda表达式(一)初始

    本篇参考Richard Warburton的 java8 Lambdas :Functional Programming for the Masses 学习lambda表达式之前,需要知道什么是函数式 ...

  9. 【Java】Java8新特性Lambda表达式和Stream API

    Lambda表达式是实现支持函数式编程技术的基础. 函数式编程与面向对象编程:函数式编程将程序代码看作数学中的函数,函数本身作为另一个函数参数或返回值,即高阶函数.而面向对象编程按照真实世界客观事物的 ...

最新文章

  1. 一文带你读懂Python的5大特点与8大应用方向!
  2. LeetCode-337 House Robber III
  3. Groovy预览--文本处理
  4. 关于Java的十件事
  5. 技术MBA打造中国未来CTO
  6. 微信 小程序 python 渲染_干货 | 微信小程序自动化测试最佳实践(附 Python 源码)...
  7. 1. Browser 对象 - Window 对象
  8. android 高通替换开机logo,高通平台 开机logo 替换
  9. Nacos指南-服务发现:删除服务
  10. Activeperl安装教程
  11. Typecho网站访问浏览总量统计插件PageViews升级版
  12. 以逗号分割数组并且去除数组最后得空数据
  13. 【凯子哥带你学Framework】Activity启动过程全解析
  14. MFC入门基础(十)静态文本框()、编辑框(Edit Control)
  15. 常微分方程编程基础(ODE)
  16. mysql练习题及答案_mysql练习题及答案.doc
  17. ubuntu批量解压分卷文件
  18. JS抽象语法树AST基础学习
  19. 使用MBROSTool 工具制作本地硬盘多启动盘的方法总结
  20. Vs2017 开发 调用 WCF

热门文章

  1. python方向难度排名_菜鸟如何提升Python编程水平?良心推荐!
  2. 腾讯千万美元购康盛打响站长争夺战
  3. vscode——HTML基本标签A标签超级链接
  4. Win8控制面板快捷键
  5. 个人总结的一些AD20版使用,对新入门选手很有帮助
  6. 【头歌】重生之我在py入门实训中(1)
  7. 2017年最新App Store审核指南(苹果官方)
  8. python语音翻译-Python 神工具包!翻译、文字识别、语音转文字统统搞定
  9. C语言指针的初步了解
  10. openfalcon 组件监控_Open-Falcon小米监控开源系统