# Java 8 Feature
# 参考文档
# 主要特性
- Lambda 表达式
- Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
- 方法引用
- 方法引用提供了非常有用的语法,可以直接引用已有 Java 类或对象(实例)的方法或构造器。与 Lambda 联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
- 函数式接口
- 接口默认方法
- 默认方法就是一个在接口里面有了一个实现的方法。
- Stream API
- 新添加的 Stream API(java.util.stream)把真正的函数式编程风格引入到 Java 中。
- Optional 类
- Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
- Date Time API
- 加强对日期与时间的处理。
- Base64
- 在 Java 8 中,Base64 编码已经成为 Java 类库的标准。
- 新工具
- 新的编译工具,如:
- Nashorn 引擎 jjs
- 类依赖分析器 jdeps
- 新的编译工具,如:
- Nashorn,JavaScript 引擎
- Java 8 提供了一个新的 Nashorn javascript 引擎,它允许我们在 JVM 上运行特定的 javascript 应用。
# Lambda
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。使用 Lambda 表达式可以使代码变的更加简洁紧凑。
目的:替代匿名类。
格式:(x,y) -> {x+y}
示例:
// 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)
2
3
4
5
6
7
8
9
10
11
12
13
14
# 变量作用域
Lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 Lambda 内部修改定义在域外的局部变量,否则会编译错误。
Lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)。
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
# 方法引用
方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
格式:使用 ::
在 Lambda 表达式中使用,可以直接传入方法签名一样的方法,即除了方法名以外,方法参数,返回值都一致。
示例:
// 以数组中的字符串为 userName 创建 User
List<String> strings = Arrays.asList("one", "two", "three", "four", "five");
// 不使用方法引用
strings.stream().map(x -> new User(x)).forEach(x -> System.out.println());
// 方法引用写法
strings.stream().map(User::new).forEach(System.out::println);
// 这里是 new User() 构造方法需要一个参数 String userName,
// 那么这里 .map(User::new) 等同于 .map(x -> new User(x))
// 这里也可以传入其他方法,只要方法签名一样就可以。
2
3
4
5
6
7
8
9
10
构造器引用:它的语法是
Class::new
,或者更一般的Class< T >::new
final Car car = Car.create( Car::new ); final List< Car > cars = Arrays.asList( car );
1
2静态方法引用:它的语法是
Class::static_method
cars.forEach( Car::collide );
1特定类的任意对象的方法引用:它的语法是
Class::method
cars.forEach( Car::repair );
1特定对象的方法引用:它的语法是
instance::method
final Car police = Car.create( Car::new ); cars.forEach( police::follow );
1
2
# 函数式接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口可以被隐式转换为 Lambda 表达式。
JDK 1.8 之前已有的函数式接口:
java.lang.Runnable
java.util.concurrent.Callable
java.util.Comparator
java.io.FileFilter
java.security.PrivilegedAction
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
包常用接口
Supplier<T>
- 0 入参 1 返回Consumer<T>
- 1 入参 0 返回Function<T,R>
- 1 入参 1 返回Predicate<T>
- 1 入参 1 boolean 返回BiConsumer<T,U>
- 2 入参 0 返回BiFunction<T,U,R>
- 2 入参 1 返回- 其它类似...
# 接口默认方法
Java 8 允许接口使用 default
关键字实现默认方法。
Java 8 接口可以声明并实现静态方法。
# Stream API
Stream 分为 stream() 串行流
和 parallelStream 并行流
。
Stream 不调用终止方法,中间操作(map、filter...)不会执行。使用 Stream.collect() 将流收集到数组、列表等集合中去。
示例:
Stream<String> stringStream = Stream.of("h", "e", "l", "l", "o");
List<String> l = stringStream.filter(c -> c.equals("l")).collect(Collectors.toList());
l.forEach(System.out::println);
2
3
# 获取 Stream 方式
- Stream.of()
- Collection/Arrays.stream()
# 中间方法
- forEach
- map
- flatMap
- filter
- sorted
- limit
- collect
# Optional 类
Optional 类的引入很好的解决空指针异常。
Optional 类是一个可以为 null
的容器对象。如果值存在则 isPresent()
方法会返回 true
,调用 get()
方法会返回该对象。
Optional 是个容器:它可以保存类型 T
的值,或者仅仅保存 null
。
Optional 提供很多有用的方法,这样我们就不用显式进行空值检测:
get()
void ifPresent(Consumer<? super T> consumer)
<U>Optional<U> map(Function<? super T,? extends U> mapper)
static <T> Optional<T> of(T value)
static <T> Optional<T> of(T value)
T orElse(T other)
T orElseGet(Supplier<? extends T> other)
<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
- ...
# Date Time API
# Base64
在 Java 8 中,Base64 编码已经成为了 Java 类库的标准,Java 8 内置了 Base64 的编/解码器。
Base64 提供了
# TODO
# 讨论区
由于评论过多会影响页面最下方的导航,故将评论区做默认折叠处理。
点击查看评论区内容,渴望您的宝贵建议~
← Java 多线程