Java 8 特性
- 1:Lambda 表达式
- 2:方法引用
- 构造器引用:
- 静态方法引用:
- 特定类的任意对象的方法引用:
- 特定对象的方法引用:
- 3:默认方法
- 静态默认方法
- 默认方法实例
- 4:新工具
- jjs
- jjs 交互式编程
- 传递参数
- Java 中调用 JavaScript
- JavaScript 中调用 Java
- 5:Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
- 6:Date Time API − 加强对日期与时间的处理。
- 7:Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
- 8:Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。
1:Lambda 表达式
− Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
在关于 Java 8 文章的实例,我们均使用 jdk 1.8 环境,你可以使用以下命令查看当前 jdk 的版本:
$ java -version
java version “1.8.0_31”
Java™ SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot™ 64-Bit Server VM (build 25.31-b07, mixed mode)
编程风格
Java 8 希望有自己的编程风格,并与 Java 7 区别开,以下实例展示了 Java 7 和 Java 8 的编程格式:
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Comparator;public class Java8Tester {public static void main(String args[]){List<String> names1 = new ArrayList<String>();names1.add("Google ");names1.add("Runoob ");names1.add("Taobao ");names1.add("Baidu ");names1.add("Sina ");List<String> names2 = new ArrayList<String>();names2.add("Google ");names2.add("Runoob ");names2.add("Taobao ");names2.add("Baidu ");names2.add("Sina ");Java8Tester tester = new Java8Tester();System.out.println("使用 Java 7 语法: ");tester.sortUsingJava7(names1);System.out.println(names1);System.out.println("使用 Java 8 语法: ");tester.sortUsingJava8(names2);System.out.println(names2);}// 使用 java 7 排序private void sortUsingJava7(List<String> names){ Collections.sort(names, new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {return s1.compareTo(s2);}});}// 使用 java 8 排序private void sortUsingJava8(List<String> names){Collections.sort(names, (s1, s2) -> s1.compareTo(s2));}
}
执行以上脚本,输出结果为:
$ javac Java8Tester.java
$ java Java8Tester
使用 Java 7 语法:
[Baidu , Google , Runoob , Sina , Taobao ]
使用 Java 8 语法:
[Baidu , Google , Runoob , Sina , Taobao ]
2:方法引用
− 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
方法引用通过方法的名字来指向一个方法。
方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
方法引用使用一对冒号 :: 。
下面,我们在 Car 类中定义了 4 个方法作为例子来区分 Java 中 4 种不同方法的引用。
package com.xxxx.main;@FunctionalInterface
public interface Supplier<T> {T get();
}class Car {//Supplier是jdk1.8的接口,这里和lamda一起使用了public static Car create(final Supplier<Car> supplier) {return supplier.get();}public static void collide(final Car car) {System.out.println("Collided " + car.toString());}public void follow(final Car another) {System.out.println("Following the " + another.toString());}public void repair() {System.out.println("Repaired " + this.toString());}
}
构造器引用:
它的语法是Class::new,或者更一般的Class< T >::new实例如下:
final Car car = Car.create( Car::new );
final List< Car > cars = Arrays.asList( car );
静态方法引用:
它的语法是Class::static_method,实例如下:
cars.forEach( Car::collide );
特定类的任意对象的方法引用:
它的语法是Class::method实例如下:
cars.forEach( Car::repair );
特定对象的方法引用:
它的语法是instance::method实例如下:
final Car police = Car.create( Car::new );
cars.forEach( police::follow );
方法引用实例
import java.util.List;
import java.util.ArrayList;public class Java8Tester {public static void main(String args[]){List<String> names = new ArrayList();names.add("Google");names.add("Runoob");names.add("Taobao");names.add("Baidu");names.add("Sina");names.forEach(System.out::println);}
}
实例中我们将 System.out::println 方法作为静态方法来引用。
执行以上脚本,输出结果为:
$ javac Java8Tester.java
$ java Java8Tester
Google
Runoob
Taobao
Baidu
Sina
3:默认方法
− 默认方法就是一个在接口里面有了一个实现的方法。
Java 8 新增了接口的默认方法。
简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。
我们只需在方法名前面加个 default 关键字即可实现默认方法。
为什么要有这个特性?
首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8 之前的集合框架没有 foreach 方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。
语法
默认方法语法格式如下:
public interface Vehicle {default void print(){System.out.println("我是一辆车!");}
}
多个默认方法
一个接口有默认方法,考虑这样的情况,一个类实现了多个接口,且这些接口有相同的默认方法,以下实例说明了这种情况的解决方法:
public interface Vehicle {default void print(){System.out.println("我是一辆车!");}
}public interface FourWheeler {default void print(){System.out.println("我是一辆四轮车!");}
}
第一个解决方案是创建自己的默认方法,来覆盖重写接口的默认方法:
public class Car implements Vehicle, FourWheeler {default void print(){System.out.println("我是一辆四轮汽车!");}
}
第二种解决方案可以使用 super 来调用指定接口的默认方法:
public class Car implements Vehicle, FourWheeler {public void print(){Vehicle.super.print();}
}
静态默认方法
Java 8 的另一个特性是接口可以声明(并且可以提供实现)静态方法。例如:
public interface Vehicle {default void print(){System.out.println("我是一辆车!");}// 静态方法static void blowHorn(){System.out.println("按喇叭!!!");}
}
默认方法实例
我们可以通过以下代码来了解关于默认方法的使用,可以将代码放入 Java8Tester.java 文件中:
public class Java8Tester {public static void main(String args[]){Vehicle vehicle = new Car();vehicle.print();}
}interface Vehicle {default void print(){System.out.println("我是一辆车!");}static void blowHorn(){System.out.println("按喇叭!!!");}
}interface FourWheeler {default void print(){System.out.println("我是一辆四轮车!");}
}class Car implements Vehicle, FourWheeler {public void print(){Vehicle.super.print();FourWheeler.super.print();Vehicle.blowHorn();System.out.println("我是一辆汽车!");}
}
执行以上脚本,输出结果为:
$ javac Java8Tester.java
$ java Java8Tester
我是一辆车!
我是一辆四轮车!
按喇叭!!!
我是一辆汽车!
4:新工具
− 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
Nashorn 一个 javascript 引擎。
Nashorn JavaScript Engine 在 Java 15 已经不可用了。
这已经在 Java 11 标记为:
@deprecated (forRemoval = true)
从 JDK 1.8 开始,Nashorn取代Rhino(JDK 1.6, JDK1.7) 成为 Java 的嵌入式 JavaScript 引擎。Nashorn 完全支持 ECMAScript 5.1 规范以及一些扩展。它使用基于 JSR 292 的新语言特性,其中包含在 JDK 7 中引入的 invokedynamic,将 JavaScript 编译成 Java 字节码。
与先前的 Rhino 实现相比,这带来了 2 到 10倍的性能提升。
jjs
jjs是个基于Nashorn引擎的命令行工具。它接受一些JavaScript源代码为参数,并且执行这些源代码。
例如,我们创建一个具有如下内容的sample.js文件:
print('Hello World!');
打开控制台,输入以下命令:
$ jjs sample.js
以上程序输出结果为:
Hello World!
jjs 交互式编程
打开控制台,输入以下命令:
$ jjs
jjs> print("Hello, World!")
Hello, World!
jjs> quit()
>>
传递参数
打开控制台,输入以下命令:
$ jjs -- a b c
jjs> print('字母: ' +arguments.join(", "))
字母: a, b, c
jjs>
Java 中调用 JavaScript
使用 ScriptEngineManager, JavaScript 代码可以在 Java 中执行,实例如下:
import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;public class Java8Tester {public static void main(String args[]){ScriptEngineManager scriptEngineManager = new ScriptEngineManager();ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn");String name = "Runoob";Integer result = null;try {nashorn.eval("print('" + name + "')");result = (Integer) nashorn.eval("10 + 2");}catch(ScriptException e){System.out.println("执行脚本错误: "+ e.getMessage());}System.out.println(result.toString());}
}
执行以上脚本,输出结果为:
$ javac Java8Tester.java
$ java Java8Tester
Runoob
12
JavaScript 中调用 Java
以下实例演示了如何在 JavaScript 中引用 Java 类:
var BigDecimal = Java.type('java.math.BigDecimal');function calculate(amount, percentage) {var result = new BigDecimal(amount).multiply(new BigDecimal(percentage)).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_EVEN);return result.toPlainString();
}var result = calculate(568000000000000000023,13.9);
print(result);
我们使用 jjs 命令执行以上脚本,输出结果如下:
$ jjs sample.js
78952000000000002017.94