侧边栏壁纸
  • 累计撰写 61 篇文章
  • 累计创建 35 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

JDK8新特性

李洪
2023-07-31 / 0 评论 / 0 点赞 / 220 阅读 / 2,272 字

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新特性之函数式接口

默认方法与静态方法

默认方法

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 Optional empty()**返回空的 Optional 实例。
2 **boolean equals(Object obj)**判断其他对象是否等于 Optional。
3 **Optional filter(Predicate<? super predicate)**如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的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 Optional of(T value)**返回一个指定非null值的Optional。
11 **static Optional ofNullable(T value)**如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。
12 **T orElse(T other)**如果存在该值,返回值, 否则返回 other。
13 **T orElseGet(Supplier<? extends T> other)**如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。
14 ** T orElseThrow(Supplier<? extends X> exceptionSupplier)**如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常
15 **String toString()**返回一个Optional的非空字符串,用来调试
0

评论区