Java8——新特性解析

Java8

  1. Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
  2. 方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
  3. 默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。
  4. Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
  5. Date Time API − 加强对日期与时间的处理。
  6. Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
  7. 函数式 - java8支持函数式编程语法
  8. 组合式异步编程 - 使用CompletableFuture构建异步应用

Lambda表示式

  1. Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
  2. Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
  3. 使用 Lambda 表达式可以使代码变的更加简洁紧凑。

语法:(parameters) -> expression 或 (parameters) ->{ statements; }

特征:

  1. 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  2. 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  3. 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  4. 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

示例:

// 1. 不需要参数,返回值为 5  
() -> 5  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

方法引用

  1. 方法引用通过方法的名字来指向一个方法。
  2. 方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
  3. 方法引用使用一对冒号 :: 。

构建方法引用:
1.指向静态方法的方法引用,例:Integer::parseInt
2.指向任意类型实例方法的方法引用,例:String::length
3.指向现有对象的实例方法的方法引用。

构造函数引用

String::new

默认方法

Java 8 新增了接口的默认方法。简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。我们只需在方法名前面加个 default 关键字即可实现默认方法。
为什么要有这个特性?
首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8 之前的集合框架没有 foreach 方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。
静态方法
Java 8 的另一个特性是接口可以声明(并且可以提供实现)静态方法。例如:

public interface Vehicle {
    // 默认方法
   default void print(){
      System.out.println("我是一辆车!");
   }
    // 静态方法
   static void blowHorn(){
      System.out.println("按喇叭!!!");
   }
}

流Stream

  1. Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
  2. Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
  3. Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
    这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
  4. 元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

什么是 Stream?
Stream(流)是一个来自数据源的元素队列并支持聚合操作

  1. 元素:是特定类型的对象,形成一个队列。Java中的Stream并不会存储元素,而是按需计算。
  2. 数据源:流的来源。可以是集合,数组,I/O channel, 产生器generator 等。
  3. 聚合操作:类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
    和以前的Collection操作不同, Stream操作还有两个基础的特征:
  4. Pipelining:中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
  5. 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
  6. 生成流:在 Java 8 中, 集合接口有两个方法来生成流:
  7. stream() : 为集合创建串行流。
  8. parallelStream() : 为集合创建并行流。

Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。在旧版的 Java 中,日期时间 API 存在诸多问题,其中有:

  1. 非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
  2. 设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
  3. 时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。

Java 8 在 java.time 包下提供了很多新的 API。以下为两个比较重要的 API:

  1. Local(本地) − 简化了日期时间的处理,没有时区的问题。
  2. Zoned(时区) − 通过制定的时区处理日期时间。
    新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。

Optional 类

  1. Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
  2. Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
  3. Optional 类的引入很好的解决空指针异常。

以下是一个 java.util.Optional 类的声明:

public final class Optional<T> extends Object

函数式

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口可以被隐式转换为 lambda 表达式。
Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。
示例:

@FunctionalInterface
interface GreetingService {
    void sayMessage(String message);
}

JDK 1.8 之前已有的函数式接口:

java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener

JDK 1.8 新增加的函数接口:

java.util.function

组合式异步编程

Future 接口
它建模了一种异步计算,返回一个执行运算结果的引用,当运算结束后,这个引用被返回给调用方。在Future中触发那些潜在耗时的操作把调用线程解放出来,让它能继续执行其他有价值的工作,不再需要呆呆等待耗时的操作完成。
例如:使用Future以异步的方式执行一个耗时的操作

ExecutorService executor = Executors.newCachedThreadPool();//创建ExecutorService,通过这个就可以向线程池提交任务
Future<Double> future = executor.submit(new Callable<Double>() {//向ExecutorService提交一个Callable对象
       public Double call() {
          return doSomeLongComputation();//以异步的方式在新的线程中执行耗时操作
       }});
doSomethingElse();//异步操作进行的同时,可以做其他事情
try {
   Double result = future.get(1, TimeUnit.SECONDS);//获取异步操作的结果,如果最终被阻塞,无法得到结果,那么在最多等待1秒钟之后退出
} catch (ExecutionException ee) {
   // 计算抛出一个异常
} catch (InterruptedException ie) {
   // 当前线程在等待过程中被中断
} catch (TimeoutException te) {
   // 在Future对象完成之前超过已过期
} 

局限性
将两个异步计算合并为一个——这两个异步计算之间相互独立,同时第二个又依赖于第一个的结果。
等待Future集合中的所有任务都完成。
仅等待Future集合中最快结束的任务完成(有可能因为它们试图通过不同的方式计算同一个值),并返回它的结果。
通过编程方式完成一个Future任务的执行(即以手工设定异步操作结果的方式)。
应对Future的完成事件(即当Future的完成事件发生时会收到通知,并能使用Future计算的结果进行下一步的操作,不只是简单地阻塞等待操作的结果)。
使用 CompletableFuture构建异步应用:(详细实现这里暂时不做介绍)

持续更新中…

发布了42 篇原创文章 · 获赞 10 · 访问量 7047

猜你喜欢

转载自blog.csdn.net/MCJPAO/article/details/102907127