JDK8新特性
-
Lambda表达式
-
方法引用
-
默认方法
-
Stream
-
Optional类
-
Nashorn,JavaScript引擎
-
新的日期时间API
-
Base64
Lambda表达式
-
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
-
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
-
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
lambda表达式的重要特征:
- **可选类型声明:**不需要声明参数类型,编译器可以统一识别参数值。
- **可选的参数圆括号:**一个参数无需定义圆括号,但多个参数需要定义圆括号。
- **可选的大括号:**如果主体包含了一个语句,就不需要使用大括号。
- **可选的返回关键字:**如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。
Lambda 表达式需要注意以下两点:
- Lambda 表达式主要用来定义行内执行的方法类型接口(例如,一个简单方法接口)。
- Lambda 表达式免去了使用匿名方法的麻烦,并且给予 Java 简单但是强大的函数化的编程能力。
变量作用域:
- lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
- lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)。
int num = 1;
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);
num = 5;
//报错信息:Local variable num defined in an enclosing scope must be final or effectively
final
- 在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
方法引用
-
方法引用通过方法的名字来指向一个方法。
-
方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
-
方法引用使用一对冒号 :: 。
-
**构造器引用:**它的语法是Class::new,或者更一般的Class< T >::new
-
**静态方法引用:**它的语法是Class::static_method
-
**特定类的任意对象的方法引用:**它的语法是Class::method
-
**特定对象的方法引用:**它的语法是instance::method
函数式接口
http://blog.hcodeclass.com/archives/jdk8新特性之函数式接口
默认方法与静态方法
默认方法
-
Java 8 对接口设计了默认方法和静态方法
compare with class
接口就完全可以替代抽象类了呢?答案是不可以的。理由有以下几点:
- 接口的变量修饰符只有
public static final
的,这明显不能满足我们的日常设计 - 接口的方法修饰符只有
public
的,这明显也不能满足我们的日常设计 - 接口不存在构造函数,也不存在
this
所以说接口替代抽象类,在 Java8 的版本上来说还不太现实。
设计目的与优势
- 为了接口的演化
先来一个 hello world 级别代码:
public interface Flyable {
void fly();
// default method
default void start() {
System.out.println("start...");
}
}
这个时候如果我们创建一个类去实现这个接口:
public class Bird implements Flyable {
@Override
public void fly() {
}
}
Java 8 之前我们知道,一个接口的所有方法其子类必须实现(当然,这个子类不是一个抽象类),但是 java 8 之后接口的默认方法可以选择不实现,如上的操作是可以通过编译期编译的。这样就避免了由 Java 7 升级到 Java 8 时项目编译报错了。
- 可以减少第三方工具类的创建
例如在 List 等集合接口中都有一些默认方法,List 接口中默认提供 replaceAll(UnaryOperator)、sort(Comparator)、spliterator() 等默认方法,这些方法在接口内部创建,避免了为了这些方法而专门去创建相应的工具类
- 可以避免创建基类
在 Java 8 之前我们可能需要创建一个基类来实现代码复用,而默认方法的出现,可以不必要去创建基类
- 更好地支持集合的 API 在 lambda 表达式中应用
举个例子,为了在 Java 8 中为了扩展 Iterator 接口的 forEach() 方法,如果我们不创建默认方法,那么的话势必会带来和接口的演化类似的问题,换句话说这一点实际上与为了接口演化类似。
注意
不能提供默认 Object 类中的方法
例如如下的操作是不允许的:
public interface Test {
default int hashCode() {
}
default boolean equals(Object object) {
}
}
- 原因有以下几点:
第一点,接口不能拥有状态,这意味着它在实现一些 Object 方法中存在一定的局限性。
第二点,Java 中如果父类和接口拥有相同的方法,子类会去优先实现父类中的方法而不是接口中的方法, 这样的话会使得我们的接口默认方法没有意义。
静态方法
设计目的与优势
- 同默认方法,静态方法的创建,可以减少创建专门的第三方工具类
注意
- 同默认方法,静态方法不能与 Object 方法同名
Stream
在 Java 8 中, 集合接口有两个方法来生成流:
- stream() − 为集合创建串行流。
- parallelStream() − 为集合创建并行流。
forEach
Stream 提供了新的方法 ‘forEach’ 来迭代流中的每个数据
map
map 方法用于映射每个元素到对应的结果
filter
filter 方法用于通过设置的条件过滤出元素
limit
limit 方法用于获取指定数量的流
Sorted
sorted 方法用于对流进行排序
并行(parallel)程序
parallelStream 是流并行处理程序的代替方法
Collectors
Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。
统计
另外,一些产生统计结果的收集器也非常有用。它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果。
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("列表中最大的数 : " + stats.getMax());
System.out.println("列表中最小的数 : " + stats.getMin());
System.out.println("所有数之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());
Optional
序号 | 方法 & 描述 |
---|---|
1 | **static |
2 | **boolean equals(Object obj)**判断其他对象是否等于 Optional。 |
3 | **Optional |
4 | ** Optional flatMap(Function<? super T,Optional> mapper)**如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional |
5 | **T get()**如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException |
6 | **int hashCode()**返回存在值的哈希码,如果值不存在 返回 0。 |
7 | **void ifPresent(Consumer<? super T> consumer)**如果值存在则使用该值调用 consumer , 否则不做任何事情。 |
8 | **boolean isPresent()**如果值存在则方法会返回true,否则返回 false。 |
9 | **Optional map(Function<? super T,? extends U> mapper)**如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。 |
10 | **static |
11 | **static |
12 | **T orElse(T other)**如果存在该值,返回值, 否则返回 other。 |
13 | **T orElseGet(Supplier<? extends T> other)**如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。 |
14 | ** |
15 | **String toString()**返回一个Optional的非空字符串,用来调试 |
评论区