java8新特性详解_Java学习之==>Java8 新特性详解

一、简介

Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级。Java 8是 Java 自 Java 5(发布于2004年)之后的最重要的版本。这个版本包含语言、编译器、库、工具和JVM等方面的十多个新特性。在本文中我们将学习这些新特性,并用实际的例子说明在什么场景下适合使用。

语言

编译器

工具

JVM

二、Java语言的新特性

1、Lambda表达式

Lambda 表达式(也称为闭包)是Java 8中最大和最令人期待的语言改变。它允许我们将函数当成参数传递给某个方法,或者把代码本身当作数据处理,函数式开发者非常熟悉这些概念。

Lambda 表达式的组成:

参数列表部分, 位于表达式左侧的括号内

(o1,o2)->{}

()->{}

x ->{}

语法标识符,或参数与代码体分隔符

->

代码块,代码体

一般多行代码使用括号包起来;

如果只有一行代码,可以省略括号不写;

有return则需写return带有返回值,如果没有则不写;

(params) -> code-body

举例:

public voidtest1(){//原始代码

new Thread(newRunnable() {

@Overridepublic voidrun() {

System.out.println("I love lambda");

}

}).start();//使用lambda之后的效果

new Thread(() -> System.out.println("I love lambda")).start();

}

Lambda表达式-函数式接口:

函数接口指的是只有一个函数的接口,这样的接口可以隐式转换为Lambda表达式。在实践中,函数式接口非常脆弱:只要某个开发者在该接口中添加一个函数,则该接口就不再是函数式接口进而导致编译失败。为了克服这种代码层面的脆弱性,并显式说明某个接口是函数式接口,Java 8 提供了一个特殊的注解@FunctionalInterface(Java 库中的所有相关接口都已经带有这个注解了),上面代码中的 Runnable 就是函数式接口,源码如下:

java8新特性详解_Java学习之==>Java8 新特性详解_第1张图片

自定义函数式接口

/*** 自定义函数式接口*/@FunctionalInterfacepublic interface FooIface{

R foo(T t, S s, U u);static voidtest2() {

}default voidtest1() {

}

}

值得注意的是,默认方法和静态方法不会破坏函数式接口的定义,因此以上的代码是合法的。

Lambda表达式-四大类函数式接口:

消费型

java.util.function.Consumer

public voidtestConsumer() {/*** 消费型

* 有参,无返回值*/Consumer consumer1 = new Consumer() {

@Overridepublic voidaccept(String s) {

System.out.println(s);

}

};

Consumer consumer2 = s ->System.out.println(s);

}

供给型

java.util.function.Supplier

public voidtestSupplier() {/*** 供给型

* 无参,有返回值

* () -> "hello";*/Supplier supplier1 = new Supplier() {

@OverridepublicString get() {return "hello";

}

};

Supplier supplier2 = () -> "hello";

}

断言型

java.util.function.Predicate

public voidtestPredicate() {/*** 断言型

* 有参数,返回值是boolean类型*/Predicate predicate1 = new Predicate() {

@Overridepublic booleantest(String s) {return s.startsWith("abc_");

}

};

Predicate predicate2 = s -> s.startsWith("abc_");

}

转化型

java.util.function.Function

public voidtestFunction() {/*** 转化型

* 有参数,有返回,但是参数和返回是不同的数据类型*/Function function1 = new Function() {

@OverridepublicInteger apply(String s) {returns.length();

}

};

Function function2 = s ->s.length();

Function function3 =String::length;

}

2、方法引用

方法引用使得开发者可以直接引用现存的方法、Java类的构造方法或者实例对象。方法引用和Lambda表达式配合使用,使得java类的构造方法看起来紧凑而简洁,没有很多复杂的模板代码。先来看一下下面这段代码:

public voidtest4() {/*** 方法引用

interface Comparator

int compare(T o1, T o2);

Integer#compare(int x, int y)

public static int compare(int x, int y) {

return (x < y) ? -1 : ((x == y) ? 0 : 1);

}*/

//原始写法,java8之前

Comparator comparator1 = new Comparator() {

@Overridepublic intcompare(Integer o1, Integer o2) {returnInteger.compare(o1, o2);

}

};//基于lambda改写后的,第一种写法,但是有冗余代码,比如return和代码块的大括号

Comparator comparator2 = (x, y) -> { returnInteger.compare(x, y); };//再一次改写,去掉了return,因为我明明知道就是要return,还需要你再写吗?

Comparator comparator3 = (x, y) ->Integer.compare(x, y);//最终,这两个形参x,y其实只是一个占位而已,接受者Integer::compare就知道有这样两个参数传进来,大家心知肚明的事情, 就省略嘛

Comparator comparator4 =Integer::compare;int x = 10;int y = 20;

System.out.println(comparator1.compare(x, y));

System.out.println(comparator2.compare(x, y));

System.out.println(comparator3.compare(x, y));

System.out.println(comparator4.compare(x, y));

}

以上这段代码写了从最原始的写法到使用 Lambda 改写后的写法再到最终的方法引用。

方法引用包括四类:

构造方法引用

Supplier supplier = String::new;

Function function = String::new;

Function function = ArrayList::new;

BiFunction biFunction = HashMap::new;

Function function = String[]::new;

静态方法引用

class::statisMethod

Comparator comparator = Integer::compare;

成员方法引用

class::Method

BiPredicate predicate = String::equals;

示例对象的方法引用

class::instanceMethod

Supplier supplier = linkedList::pop;

自定义类实现方法引用

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classStringLengthCompare {public static intabc(String o1, String o2) {return o1.length() > o2.length() ? 1 : -1;

}public intbcd(String o1, String o2) {return o1.length() > o2.length() ? 1 : -1;

}

}

StringLengthCompare 类

public voidtest5() {/*** 第一种,原始写法*/Comparator comparator = new Comparator() {

@Overridepublic intcompare(String o1, String o2) {return o1.length() > o2.length() ? 1 : -1;

}

};int res = comparator.compare("abc", "ab");

System.out.println(res);/*** 第二种,使用lambda改写*/Comparator comparator1 = (str1, str2) -> str1.length() > str2.length() ? 1 : -1;

res= comparator1.compare("abc", "ab");

System.out.println(res);/*** 第三种,自定义StringLengthCompare类实现方法引用*/

//abc为静态方法,直接用类名调用

Comparator comparator2 =StringLengthCompare::abc;

System.out.println("comparator2 = " +comparator2);//bcd为非静态方法,需要用对象来调用

StringLengthCompare stringLengthCompare = newStringLengthCompare();

Comparator comparator3 =stringLengthCompare::bcd;

System.out.println("comparator3 = " +comparator3);

}

3、接口的静态方法和默认方法

Java 8 使用两个新概念扩展了接口的含义:默认方法和静态方法。默认方法使得开发者可以在不破坏二进制兼容性的前提下,往现存接口中添加新的方法,即不强制那些实现了该接口的类也同时实现这个新加的方法。默认方法和抽象方法之间的区别在于抽象方法需要实现,而默认方法不需要。接口提供的默认方法会被接口的实现类继承或者覆写,例子代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

private interfaceDefaulable {//Interfaces now allow default methods, the implementer may or//may not implement (override) them.

defaultString notRequired() {return "Default implementation";

}

}

Defaulable

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

private static class DefaultableImpl implementsDefaulable {

}

DefaultableImpl

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

private static class OverridableImpl implementsDefaulable {

@OverridepublicString notRequired() {return "Overridden implementation";

}

}

OverridableImpl

Defaulable 接口使用关键字 default 定义了一个默认方法 notRequired()。DefaultableImpl 类实现了这个接口,同时默认继承了这个接口中的默认方法;OverridableImpl 类也实现了这个接口,但覆写了该接口的默认方法,并提供了一个不同的实现。

Java 8带来的另一个有趣的特性是在接口中可以定义静态方法,例子代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

private interfaceDefaulableFactory {//Interfaces now allow static methods

static Defaulable create( Supplier< Defaulable >supplier ) {returnsupplier.get();

}

}

DefaulableFactory

下面的代码片段整合了默认方法和静态方法的使用场景:

public static voidmain( String[] args ) {

Defaulable defaulable= DefaulableFactory.create( DefaultableImpl::new);

System.out.println( defaulable.notRequired() );

defaulable= DefaulableFactory.create( OverridableImpl::new);

System.out.println( defaulable.notRequired() );

}

这段代码输入结果如下:

Default implementation

Overridden implementation

由于JVM上的默认方法的实现在字节码层面提供了支持,因此效率非常高。默认方法允许在不打破现有继承体系的基础上改进接口。该特性在官方库中的应用是:给java.util.Collection接口添加新方法,如stream()、parallelStream()、forEach() 和removeIf() 等等。尽管默认方法有这么多好处,但在实际开发中应该谨慎使用:在复杂的继承体系中,默认方法可能引起歧义和编译错误。

注意:实现接口的类或者子接口不会继承接口中的静态方法

4、重复注解

在 Java学习之==>注解这篇文章中有关于重复注解的介绍和使用。重复注解也是在 Java 8 中才开始支持的。

三、Java 官方库的新特性

1、Streams

新增的 Stream API(java.util.stream)将函数式编程引入了 Java 库中。这是目前为止最大的一次对 Java 库的完善,以便开发者能够写出更加有效、更加简洁和紧凑的代码。Steam API 极大的简化了集合操作(后面我们会看到不止是集合)。

Stream概述

非主流式定义: 像写SQL一样来处理集合;

理解类定义: 流式处理;

流式处理学习路线: 创建,操作(中间操作,终止操作);

Stream创建

Collection等集合接口实现的stream()方法和parallelStream()方法;

Arrays提供的数组流;

Stream类提供的静态创建方法of();

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classDemo {public static voidmain(String[] args) {/*** 创建Stream流,有三种方式*/

//第一种,集合类自带的方法

List list = new ArrayList<>();

Stream stream =list.stream();

Set set = null;

Stream stream1 =set.stream();//第二种,数组类流的创建

int[] arr = new int[]{1, 2, 3};

IntStream stream2=Arrays.stream(arr);/*** public static Stream of(T... values) {

* return Arrays.stream(values);

* }*/

//第三种,Stream接口自己提供的of方法,从实现来看是和第二种是一样的

Stream stream3 = Stream.of("", "", "");

}

}

创建Stream流的三种方式

Stream中间操作

过滤::filter;

切片 & 分页:sklip , limit;

去重:distinct(去重的对象需要实现hashCode和equals);

映射:map, flatMap;

排序:sort;

Stream终止操作

匹配

allMatch:检查是否匹配所有元素;

anyMatch:检查是否匹配至少一个元素;

noneMatch:检查是否没有匹配所有元素

查找

findFirst:查找找到的第一个元素;

findAny:查找找到的任意一个元素

计算流中元素个数:count();

计算流中元素的最大/最小值:max() , min();

内部迭代:forEach;

收集:collect;

下面我们来举例操作一下:

首先定义两个实体类 Account 和 User

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

@Setter

@Getter

@ToStringpublic classAccount {private intid;privateString accountName;private booleanisInner;private booleanisA;private booleanisB;private booleanisC;privateString type;private Listusers;privateAccount() {

}private Account(int id, String accountName, boolean isInner, String type, Listusers) {this.id =id;this.accountName =accountName;this.isInner =isInner;this.type =type;this.users =users;

}public Account(int id, String accountName, boolean isInner, boolean isA, boolean isB, booleanisC,

String type) {this.id =id;this.accountName =accountName;this.isInner =isInner;this.isA =isA;this.isB =isB;this.isC =isC;this.type =type;

}public static Account of(int id, String accountName, booleanisInner, String type,

Listusers) {return newAccount(id, accountName, isInner, type, users);

}public static Account of(int id, String accountName, boolean isInner, boolean isA, booleanisB,booleanisC,

String type) {return newAccount(id, accountName, isInner, isA, isB, isC, type);

}

@Overridepublic booleanequals(Object o) {if (this ==o) {return true;

}if (o == null || getClass() !=o.getClass()) {return false;

}

Account account=(Account) o;if (id !=account.id) {return false;

}return accountName != null ?accountName.equals(account.accountName)

: account.accountName== null;

}

@Overridepublic inthashCode() {int result =id;

result= 31 * result + (accountName != null ? accountName.hashCode() : 0);returnresult;

}

}

Account

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

@Setter

@Getter

@ToStringpublic classUser {private intid;privateString name;privateUser() {

}private User(intid, String name) {this.id =id;this.name =name;

}public static User of(intid, String name) {return newUser(id, name);

}//@Override//public boolean equals(Object o) {//if (this == o) {//return true;//}//if (o == null || getClass() != o.getClass()) {//return false;//}//User user = (User) o;//return id == user.id &&//Objects.equal(name, user.name);//}//

//@Override//public int hashCode() {//return Objects.hashCode(id, name);//}

@Overridepublic booleanequals(Object o) {if (this ==o) {return true;

}if (o == null || getClass() !=o.getClass()) {return false;

}

User user=(User) o;return id ==user.id;

}

@Overridepublic inthashCode() {returnObjects.hashCode(id);

}

}

User

生成 Account 对象集合的类 AccountFactory

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classAccountFactory {public static ListgetSimpleAccounts() {

List accounts = new ArrayList<>();

accounts.add(Account.of(1, "微信支付1账户", false, "出款", UserFactory.getSimpleUsers(true)));

accounts.add(Account.of(2, "微信支付2账户", false, "入款", UserFactory.getSimpleUsers(true)));

accounts.add(Account.of(3, "微信支付3账户", true, "出款", UserFactory.getSimpleUsers(false)));

accounts.add(Account.of(4, "微信支付4账户", true, "入款", UserFactory.getSimpleUsers(true)));

accounts.add(Account.of(5, "微信支付5账户", false, "出款", UserFactory.getSimpleUsers(false)));

accounts.add(Account.of(6, "微信支付6账户", false, "入款", UserFactory.getSimpleUsers(true)));

accounts.add(Account.of(7, "微信支付7账户", false, "出款", UserFactory.getSimpleUsers(false)));

accounts.add(Account.of(8, "微信支付8账户", true, "出款", UserFactory.getSimpleUsers(true)));

accounts.add(Account.of(9, "微信支付9账户", true, "入款", UserFactory.getSimpleUsers(false)));

accounts.add(Account.of(10, "微信支付10账户", true, "出款", UserFactory.getSimpleUsers(true)));

accounts.add(Account.of(11, "微信支付11账户", true, "入款", UserFactory.getSimpleUsers(true)));

accounts.add(Account.of(12, "微信支付12账户", false, "出款", UserFactory.getSimpleUsers(true)));returnaccounts;

}public static ListgetSimpleABCAccounts() {

List accounts = new ArrayList<>();

accounts.add(Account.of(1, "微信支付1账户", false, false, true, true, "出款"));

accounts.add(Account.of(2, "微信支付2账户", false, false, false, true, "入款"));

accounts.add(Account.of(3, "微信支付3账户", true, false, true, false, "出款"));

accounts.add(Account.of(4, "微信支付4账户", true, false, true, true, "入款"));

accounts.add(Account.of(5, "微信支付5账户", false, false, false, false, "出款"));

accounts.add(Account.of(6, "微信支付6账户", false, false, true, true, "入款"));

accounts.add(Account.of(7, "微信支付7账户", false, false, false, false, "出款"));

accounts.add(Account.of(8, "微信支付8账户", true, false, false, true, "出款"));

accounts.add(Account.of(9, "微信支付9账户", true, false, true, true, "入款"));

accounts.add(Account.of(10, "微信支付10账户", true, false, false, false, "出款"));

accounts.add(Account.of(11, "微信支付11账户", true, false, false, true, "入款"));

accounts.add(Account.of(12, "微信支付12账户", false, false, true, true, "出款"));returnaccounts;

}public static void printAccount(Listaccounts) {for(Account account : accounts) {

System.out.println("account = " +account);

}

}public static void printAccount(Map>accounts) {

accounts.forEach((key, val)->{

System.out.println("groupName:" +key);for(Account account : val) {

System.out.println("\t\t account:" +account);

}

});

}

}

AccountFactory

生成 User 对象集合的类 UserFactory

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classUserFactory {public static List getSimpleUsers(booleantype) {

List users =Lists.newArrayList();if(type) {

users.add(User.of(1, "张三"));

users.add(User.of(1, "李四"));

users.add(User.of(1, "王五"));

}else{

users.add(User.of(1, "张三"));

users.add(User.of(1, "李四"));

users.add(User.of(1, "王五"));

users.add(User.of(1, "王二麻子"));

users.add(User.of(1, "小淘气"));

}returnusers;

}public static ListgetSimpleUsers() {

List users =Lists.newArrayList();

users.add(User.of(1, "张三"));

users.add(User.of(1, "李四"));

users.add(User.of(1, "王五"));

users.add(User.of(1, "王五"));

users.add(User.of(1, "王五"));

users.add(User.of(1, "王五"));

users.add(User.of(1, "王五"));

users.add(User.of(1, "王二麻子"));

users.add(User.of(1, "小淘气"));returnusers;

}

}

UserFactory

以下为测试代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classStreamDemo1 {/*** 过滤:原始写法*/@Testpublic voidtest1() {

List accounts =AccountFactory.getSimpleAccounts();

List accs = new ArrayList<>();for(Account account : accounts) {if(account.isInner()) {

accs.add(account);

}

}

AccountFactory.printAccount(accs);

}/*** 过滤:java8写法*/@Testpublic voidtest2() {

List accounts =AccountFactory.getSimpleAccounts();

List accs =accounts

.stream()//创建流

.filter(Account::isInner) //中间操作

.collect(Collectors.toList()); //终止操作

AccountFactory.printAccount(accs);

}/*** 分组:原始写法*/@Testpublic voidtest3() {

List accounts =AccountFactory.getSimpleAccounts();

Map> group = new HashMap<>();for(Account account : accounts) {if(group.containsKey(account.getType())) {

group.get(account.getType()).add(account);

}else{

List acc = new ArrayList<>();

acc.add(account);

group.put(account.getType(), acc);

}

}

AccountFactory.printAccount(group);

}/*** 分组:java8的写法*/@Testpublic voidtest4() {

List accounts =AccountFactory.getSimpleAccounts();

Map> group =accounts

.stream()

.collect(Collectors.groupingBy(Account::getType));

AccountFactory.printAccount(group);

}/*** 分组, 对内部账户进行分组*/@Testpublic voidtest5() {

List accounts =AccountFactory.getSimpleAccounts();

Map> group = new HashMap<>();for(Account account : accounts) {if (!account.isInner()) {continue;

}if(account.isA()) {continue;

}if (!account.isB()) {continue;

}if(group.containsKey(account.getType())) {

group.get(account.getType()).add(account);

}else{

List acc = new ArrayList<>();

acc.add(account);

group.put(account.getType(), acc);

}

}

AccountFactory.printAccount(group);

}/*** 基于java8的分组,对内部账户进行分组*/@Testpublic voidtest6() {

List accounts =AccountFactory.getSimpleAccounts();

Map> group =accounts

.stream()

.filter(Account::isInner)

.filter(account-> !account.isB())

.filter(Account::isC)

.collect(Collectors.groupingBy(Account::getType));

AccountFactory.printAccount(group);

}

@Testpublic voidtest7() {/*** filter是中间操作

* filter操作完以后Stream对象类型不变*/Stream stream = Stream.of("abc_d", "ef", "abc_123")

.filter(str-> str.startsWith("abc_"));/*** collect是终止操作

* collect操作完以后Stream对象类型变成其他类型了*/List collect = Stream.of("abc_d", "ef", "abc_123")

.filter(str-> str.startsWith("abc_"))

.collect(Collectors.toList());for(String s : collect) {

System.out.println(s);

}

}

}

StreamDemo1

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classStreamDemo2 {/*** map:映射,获取对象的某个属性

* 返回所有内部账户的账户名*/@Testpublic voidtestMap() {

List accounts =AccountFactory.getSimpleAccounts();

List list =accounts.stream()

.filter(Account::isInner)

.map(Account::getAccountName)

.collect(Collectors.toList());for(String s : list) {

System.out.println(s);

}

}/*** skip:切片,去除前面几条*/@Testpublic voidtestSkip() {

List accounts =AccountFactory.getSimpleAccounts();

List list =accounts

.stream()

.skip(5)

.collect(Collectors.toList());for(Account account : list) {

System.out.println(account);

}

}/*** skip:切片,去除调前面几条

* limit:分页,控制结果的数量*/@Testpublic voidtestLimit() {

List accounts =AccountFactory.getSimpleAccounts();

List list =accounts

.stream()

.skip(3)

.limit(5)

.collect(Collectors.toList());for(Account account : list) {

System.out.println(account);

}

}/*** 拿出account中user列表的名字

*

* 去重*/@Testpublic voidtestflatMap() {

List accounts =AccountFactory.getSimpleAccounts();//这个搞不定

List> res =accounts.stream()

.map(account->{

List users =account.getUsers();returnusers.stream().map(User::getName).collect(Collectors.toList());

})

.distinct()

.collect(Collectors.toList());

System.out.println("res:" +res);

List res2 =accounts.stream()//[[1,2],[1,2,3],[1,2,3,4]]

.flatMap(account ->account.getUsers().stream())//[1,2,1,2,3,1,2,3,4]

.map(User::getName)

.distinct()

.collect(Collectors.toList());

System.out.println("res2:" +res2);

}

}

StreamDemo2

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classStreamDemo3 {

@Testpublic voidtestMaxOrMin() {

List accounts =AccountFactory.getSimpleAccounts();

Optional optional =accounts.stream()

.filter(Account::isInner)

.map(Account::getId)/*** peek,调试时输出值*/.peek(System.out::println)

.max(Integer::compare);

Integer maxId=optional.get();

System.out.println("maxId = " +maxId);

}

@Testpublic voidtestForeach() {

List accounts =AccountFactory.getSimpleAccounts();

accounts.stream()

.filter(Account::isInner)

.map(Account::getId)

.forEach(System.out::println);

}

@Testpublic voidtestFind() {

List accounts =AccountFactory.getSimpleAccounts();

Optional optional =accounts.stream()

.filter(Account::isInner)

.map(Account::getId)

.findAny();

System.out.println("optional.get() = " +optional.get());

}

@Testpublic voidtestMatch() {

List accounts =AccountFactory.getSimpleAccounts();boolean match =accounts.stream()

.anyMatch(Account::isInner);

System.out.println("match = " +match);

}

@Testpublic voidtestMapForeach() {

Map mapData =Maps.newHashMap();

mapData.put("hello", "hi");

mapData.put("yes", "no");

mapData.forEach((key, val)->{

System.out.println(key+ "," +val);

});

}

}

StreamDemo3

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classStreamDemo4 {/*** 我以accountName作为key,来划分Account

*

* list = [account,account]

*

* map = {(accountName,account),(accountName,account)} map =

* {(accountName,account),(accountName,account)}*/@Testpublic voidtest1() {

List accounts =AccountFactory.getSimpleAccounts();

Map map =accounts

.stream()

.collect(Collectors.toMap(Account::getAccountName, account->account));

map.forEach((key, val)->{

System.out.println(key+ "," +val);

});

}

@Testpublic voidtest2(){

List accounts =AccountFactory.getSimpleAccounts();

Map map =accounts

.stream()

.collect(Collectors.toMap(Account::getAccountName, Account::getId));

map.forEach((key, val)->{

System.out.println(key+ "," +val);

});

}

}

StreamDemo4

2、Date/Time API(JSR 310)

3、Optional

简介

Optional 类是一个可以为 null 的容器对象。如果值存在则 isPresent() 方法会返回true,调用get()方法会返回该对象。

Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

Optional 类的引入很好的解决空指针异常。

类的属性和方法

java8新特性详解_Java学习之==>Java8 新特性详解_第2张图片

从图中我们可以看出,它的构造方法都是private修饰的,其实是一个单例模式的应用。

下面我们主要来讲一下 filter() 和 map() 方法:

filter 方法

该方法是过滤方法,过滤符合条件的 Optional 对象,这里的条件用 Lambda 表达式来定义,源码如下:

public Optional filter(Predicate super T>predicate) {//如果入参predicate对象为null将抛NullPointerException异常

Objects.requireNonNull(predicate);//如果Optional对象的值为null,将直接返回该Optional对象

if (!isPresent())return this;//如果Optional对象的值符合限定条件(Lambda表达式来定义),返回该值,否则返回空的Optional对象

else

return predicate.test(value) ? this: empty();

}

map 方法

map方法用于修改该值,并返回修改后的Optional对象,一般会在多级取值的时候用到,源码如下:

public Optional map(Function super T, ? extends U>mapper) {//如果入参mapper对象为null将抛NullPointerException异常

Objects.requireNonNull(mapper);//如果Optional对象的值为null,将直接返回该Optional对象

if (!isPresent())returnempty();//执行传入的lambda表达式,并返回经lambda表达式操作后的Optional对象

else{returnOptional.ofNullable(mapper.apply(value));

}

}

举例:

判断不为null然后进行操作

public classDemo {/*** 不为null时进行操作

* 原始写法*/

public static voiddoThing(String name) {if (name != null) {

System.out.println(name);

}

}//使用Optional的写法

public static voiddoThingOptional(String name) {

Optional.ofNullable(name).ifPresent(System.out::println);

}

}

多层级取值

public classDemo {//原始写法

public staticString getAddress(User user) {if (user != null) {

AddressEntity addressEntity=user.getAddressEntity();if (addressEntity != null) {

String address=addressEntity.getAddress();if (address != null && address.length() > 3) {returnaddress;

}

}

}return null;

}//使用Optional的写法

public staticString getAddressOptional(User user) {returnOptional.ofNullable(user)

.map(u->u.getAddressEntity())

.map(a->a.getAddress())

.filter(s-> s.length() > 3)

.orElse(null);

}

}

四、JVM 的新特性

使用Metaspace(JEP 122)代替持久代(PermGen space)。在JVM参数方面,使用-XX:MetaSpaceSize和-XX:MaxMetaspaceSize代替原来的-XX:PermSize和-XX:MaxPermSize。

你可能感兴趣的:(java8新特性详解)