java面试新特性_JDK8 新特性最全讲解,囊括面试高频知识点

序言

JDK 8 日渐成为项目开发中的主流。

但平时在和很多小伙伴的交流和面试中,发现很多人仍停留在 JDK 7 及以前的认知层面,Lambda 表达式、方法引用、Stream 流、default 关键字,很少使用,甚至还有不少小伙伴不知道怎么用!!

不客气地说,不掌握 JDK 8 的新特性,面试通过基本很难很难。换位思考,若不掌握,你面试不慌吗?

本文会帮你详细梳理 JDK 8 中的新特性,有原理讲解,有示例实战,助力你面试起飞。

提前预警,本文很长!但一定是干货满满的,对于技术文章而言,短小精悍的特点并不是好事,因此我写的文章都偏长,注重干货,注重前因后果,做到知其然更要知其所以然。如果你有耐心读下去,一定会有较大收获。

如果没耐心看下去,或没时间看,请直接跳到最后的第四节,可微信公众号收藏留以备用~

一、Lambda 表达式

在 Java 语言中使用 Lambda 表达式,是 JDK 8 推出的最重要特性之一。它能够简化我们的传统操作。

在具体描述 Lambda 表达式之前,我们需要补充一些基础知识:什么是函数式接口。

1.1 函数式接口的定义

提到函数式接口(unctional interface),就牵扯到一个注解:@FunctionInterface。

所谓函数式接口,是指的一类添加了 @FunctionInterface 注解的接口。换言之,只要一个接口有 @FunctionInterface 注解,那这个接口就是函数式接口。

举个例子就明白了。

当你在对任务 taskA 处理时,如果想异步处理,不影响主干流程的继续进行,你会怎么做?

初级版:新增一个类,实现 Runnable 接口

你会说很简单呐,另起一个线程去执行任务 taskA 就可以了呀,喏,如下:

/**

* @author: sss

*/

public class TaskAThread implements Runnable {

@Override

public void run() {

// process taskA

...

}

}

public class Main {

public static void main(String[] args) {

// new 一个新线程,执行任务A

Runnable taskA = new TaskAThread();

new Thread(taskA).start();

// 主线程继续做其他事情

System.out.println("do other things...");

}

}

这种方式是可以实现,但有没有其他方式呢?

进阶版:使用匿名内部类

有些小伙伴明显的发现了上面代码中的问题:繁琐!!只是为了创建一个线程并使用它的 run() 方法,还要新增一个类,没有必要,直接使用匿名类就解决啦:

public class Main {

public static void main(String[] args) {

// 通过匿名类来创建一个新线程,执行任务A

Runnable taskA = new Runnable() {

@Override

public void run() {

// process taskA

...

}

};

new Thread(taskA).start();

// 主线程继续做其他事情

System.out.println("do other things...");

}

}

通过匿名类的方式,省去了新增一个类的操作,大大简化。但若使用 Lambda 的方式,会更加简洁。

高级版:使用 Lambda 表达式

public static void main(String[] args) {

// 通过匿名类来创建一个新线程,执行任务A

new Thread(() -> {

System.out.println("正在异步处理 taskA 中...");

// do things

...

}).start();

// 主线程继续做其他事情

System.out.println("do other things...");

}

有没有发现很神奇,类似 () -> {...} 的这种箭头式写法竟然能通过编译!而且还能运行(不信的小伙伴可以试试)!这种就是 Lambda 表达式的其中一种写法,不理解的小伙伴也没关系,我们后面会详细解释。

也许这种 Lambda 写法很多小伙伴见过,并习以为常,但为什么可以运行,你知道根本原因吗?

这里就体现出函数式接口的作用了。我们去看一下 JDK 7 和 JDK 8 中关于 Runnable 接口的定义,如下。大家有发现什么不同点了吗?

b15a063c7df85a7b2b8b36c1e7af722e.png

眼尖的小伙伴一定发现了,JDK 8 中多了个注解 @FunctionalInterface。这就是为何能在 JDK 8 中可以使用这种箭头式的 Lambda 写法。

本小节最开始时我们也提到了此注解。从上图也能看出,@FunctionalInterface 是JDK 8 中新引入的一个注解,它定义了一类新的接口(即函数式接口),该类接口有且只能有一个抽象方法。

它主要用于编译期的错误检查,如果一个接口不包含抽象方法(Serializable、Cloneable 等标记接口),或者包含多个抽象方法,都不符合 @FunctionalInterface 注解的定义,加了就会出错,如下这种:

// 错误示例 1

@FunctionalInterface

interface InvalidInterfaceA {

}

// 错误示例 2

@FunctionalInterface

interface InvalidInterfaceB {

void testA();

void testB();

}

正确示范:

@FunctionalInterface

interface InvalidInterfaceC {

void testC();

}

@FunctionalInterface

interface InvalidInterfaceD {

void testD();

default void testE() {

System.out.println("this is a default method.");

}

}

@FunctionalInterface 修饰的接口,只能有一个抽象方法,但并代表只能有一个方法声明,像上面的 InvalidInterfaceD 接口,还有 default 关键字修饰的 testE() 方法,但这是一个有默认实现的方法,并不是抽象方法,因此接口 InvalidInterfaceD 依然符合函数式接口的定义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值