JDK 8 新特性
Posted xp0813
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK 8 新特性相关的知识,希望对你有一定的参考价值。
1. 了解Open JDK 和 Oracle JDK
2. JDK 8新特性
Lambda 表达式
集合之 Stream流式操作
接口的增强
并行数组排序
Optional 中避免Null检查
新的时间和日期 API
可重复注解
1.Lambda 表达式介绍
1.1使用匿名内部类存在的问题
当需要启动一个线程去完成任务时,通常会通过 Runnable 接口来定义任务内容,并使用 Thread 类来启动该线程。
传统写法,代码如下:
public class Demo01LambdaIntro { public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { System.out.println("新线程任务执行!"); } }).start(); } }
由于面向对象的语法要求,首先创建一个 Runnable 接口的匿名内部类对象来指定线程要执行的任务内容,再将其交给一个线程来启动。
代码分析:对于 Runnable 的匿名内部类用法,可以分析出几点内容:Thread 类需要 Runnable 接口作为参数,其中的抽象 run 方法是用来指定线程任务内容的核心为了指定 run 的方法体,
不得不需要 Runnable 接口的实现类为了省去定义一个 Runnable 实现类的麻烦,不得不使用匿名内部类必须覆盖重写抽象 run 方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错而实际上,
似乎只有方法体才是关键所在
1.2Lambda体验
Lambda是一个匿名函数,可以理解为一段可以传递的代码。
Lambda表达式写法,代码如下:
借助Java 8的全新语法,上述 Runnable 接口的匿名内部类写法可以通过更简单的Lambda表达式达到相同的效果
public class Demo01LambdaIntro {
public static void main(String[] args) {
new Thread(() -> System.out.println("新线程任务执行!")).start(); // 启动线程
}
}
这段代码和刚才的执行效果是完全一样的,可以在JDK 8或更高的编译级别下通过。从代码的语义中可以看出:我们
启动了一个线程,而线程任务的内容以一种更加简洁的形式被指定。
我们只需要将要执行的代码放到一个Lambda表达式中,不需要定义类,不需要创建对象。
1.3Lambda的优点
简化匿名内部类的使用,语法更加简单。
小结:了解了匿名内部类语法冗余,体验了Lambda表达式的使用,发现Lmabda是简化匿名内部类的简写
1.4Lambda 的标准格式
Lambda省去面向对象的条条框框,Lambda的标准格式格式由3个部分组成:
( 参数类型 参数名称) -> {
代码体;
}
格式说明:
( 参数类型 参数名称):参数列表
{ 代码体;}:方法体
- > :箭头,分隔参数列表和方法体
Lambda与方法的对比
匿名内部类
public void run() {
System.out.println("aa");
}
Lambda
() -> System.out.println("bb!")
1.4.1练习无参数无返回值的Lambda
interface Swimmable { public abstract void swimming(); }
package com.itheima.demo01lambda; public class Demo02LambdaUse {
public static void main(String[] args) {
goSwimming(new Swimmable() {
@Override
public void swimming() {
System.out.println("匿名内部类游泳");
}
});
goSwimming(() -> {
System.out.println("Lambda游泳");
});
}
public static void goSwimming(Swimmable swimmable) {
swimmable.swimming();
}
}
1.4.2练习有参数有返回值的Lambda
下面举例演示 java.util.Comparator<T> 接口的使用场景代码,其中的抽象方法定义为:
public abstract int compare(T o1, T o2);
当需要对一个对象集合进行排序时, Collections.sort 方法需要一个 Comparator 接口实例来指定排序的规则。
传统写法
如果使用传统的代码对 ArrayList 集合进行排序,写法如下:
public class Person { private String name; private int age; private int height; // 省略其他 }
package com.itheima.demo01lambda; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; public class Demo03LambdaUse { public static void main(String[] args) { ArrayList<Person> persons = new ArrayList<>(); persons.add(new Person("刘德华", 58, 174)); persons.add(new Person("张学友", 58, 176)); persons.add(new Person("刘德华", 54, 171)); persons.add(new Person("黎明", 53, 178)); Collections.sort(persons, new Comparator<Person>() { @Override public int compare(Person o1, Person o2) { return o1.getAge() - o2.getAge(); } }); for (Person person : persons) { System.out.println(person); } } }
这种做法在面向对象的思想中,似乎也是“理所当然”的。其中 Comparator 接口的实例(使用了匿名内部类)代表 了“按照年龄从小到大”的排序规则。
Lambda写法
package com.itheima.demo01lambda; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; public class Demo03LambdaUse {
public static void main(String[] args) {
ArrayList<Person> persons = new ArrayList<>();
persons.add(new Person("刘德华", 58, 174));
persons.add(new Person("张学友", 58, 176));
persons.add(new Person("刘德华", 54, 171));
persons.add(new Person("黎明", 53, 178)); Collections.sort(persons, (o1, o2) -> {
return o1.getAge() - o2.getAge();
}); for (Person person : persons) {
System.out.println(person);
}
System.out.println("-----------------"); List<Integer> list = Arrays.asList(11, 22, 33, 44); list.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});
System.out.println("-----------------");
list.forEach((s) -> { System.out.println(s); });
} }
1.4.3Lambda表达式的标准格式
(参数列表) -> { 方法体; }
1.5Lambda的实现原理
我们现在已经会使用Lambda表达式了。现在同学们肯定很好奇Lambda是如何实现的,现在我们就来探究Lambda 表达式的底层实现原理。
@FunctionalInterface
interface Swimmable {
public abstract void swimming();
} public class Demo04LambdaImpl {
public static void main(String[] args) {
goSwimming(new Swimmable() {
@Override
public void swimming() {
System.out.println("使用匿名内部类实现游泳");
}
});
} public static void goSwimming(Swimmable swimmable) {
swimmable.swimming();
}
}
我们可以看到匿名内部类会在编译后产生一个类: Demo04LambdaImpl$1.class
以上是关于JDK 8 新特性的主要内容,如果未能解决你的问题,请参考以下文章