章
目
录
在本篇文章中,我们提供了最重要最常见的 Java 8 面试问题及其答案整理,当前还包含代码示例和说明:
本文中列出的所有重要问题都特定于 Java 8。随着新版本的推出,Java 已经(随着时间的推移)发生了很大的变化。对于每个版本,都会有一些新增功能,而现在企业中比较主流的仍然是Java8。本文将介绍相关重要的面试知识点。
这些是非常常见的问题,在任何需要高级技能的 Java 面试中都会问到这些问题。也是一些大厂非常喜欢问的问题。本文将非常适合 Java 开发人员以及 Java 测试人员/自动化测试人员或任何在同一领域追求更高薪水的人。
最常见的 Java 8 面试题及答案
面试题1: 列出 Java 8 中引入的新特性?
答: Java 8 中引入的新特性如下:
- Lambda 表达式:Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
- 方法引用:方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少默认方法: 默认方法就是一个在接口里面有了一个实现的方法。
- 新工具:新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
- Optional 类: Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
- Nashorn, JavaScript 引擎: Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。
- Stream API:新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
- Date Time API: 加强对日期与时间的处理。
面试题2: 什么是FunctionalInterface ?
答:FunctionalInterface也称为“函数式接口”, 是只有一个抽象方法的接口。这些接口的实现是使用 Lambda 表达式提供的,这意味着要使用 Lambda 表达式,需要创建一个新的函数式接口,或者可以使用Java 8 的预定义函数式接口。
用于创建新FunctionalInterface 的注解是@FunctionalInterface 。
JDK中的函数式接口举例如下:
- java.lang.Runnable,
- java.awt.event.ActionListener,
- java.util.Comparator,
- java.util.concurrent.Callable
- java.util.function包下的接口,如Consumer、Predicate、Supplier等
面试题3: 什么是Optional 类?
答:Optional 类是 Java 8 中引入的一个特殊包装类,用于避免 NullPointerException。这个类存在于 java.util 包下。当我们未能执行 Null 检查时会发生 NullPointerException。
面试题4: 默认方法是什么?
答:简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。我们只需在方法名前面加个 default 关键字即可实现默认方法。
语法:
public interface questions{
default void print() {
System.out.println("www.panziye.com");
}
}
面试题5: Lambda表达式的主要特点是什么?
- 定义为 Lambda 表达式的方法可以作为参数传递给另一个方法。
- 方法可以独立存在而不属于某个类。
- 无需声明参数类型,因为编译器可以从参数值中获取类型。
- 使用多个参数时可以使用括号,但使用单个参数时不需要括号。
- 如果表达式主体只有一条语句,则无需包含花括号。
面试题6:旧版本的日期和时间有什么缺点?
答: 下面列出的是旧日版本期和时间的缺点:
- java.util.Date 是可变的并且不是线程安全的,而新的 Java 8 日期和时间 API 是线程安全的。
- Java 8 日期和时间 API 符合 ISO 标准,而旧的日期和时间设计不佳。
- 它为日期引入了几个 API 类,如 LocalDate、LocalTime、LocalDateTime 等。
- 谈到两者之间的性能,Java 8 比旧的日期和时间机制运行得更快。
面试题7: Collection API 和 Stream API 有什么区别?
答: Stream API 和 Collection API 的区别可以从下表中理解:

面试题8:如何创建函数式接口?
答:可以用注解@FunctionalInterface自定义一个函数式接口。一旦定义了功能接口,就只能有一个抽象方法。由于您只有一个抽象方法,因此您可以编写多个静态方法和默认方法。
下面是为两个数字相乘而编写的 FunctionalInterface 的编程示例。
@FunctionalInterface
interface FuncInterface {
public int multiply(int a, int b);
}
public class Java8 {
public static void main(String args[]) {
FuncInterface Total = (a, b) -> a * b;
System.out.println("Result: "+Total.multiply(30, 60));
}
}
面试题9: 什么是 SAM 接口?
答: Java 8 引入了 FunctionalInterface 的概念,它只能有一个抽象方法。由于这些接口仅指定一种抽象方法,因此有时将它们称为 SAM 接口。SAM 代表“单一抽象方法”。
面试题10:什么是方法引用?
答:在 Java 8 中,引入了一个新特性,称为方法引用。这是用来指函数式接口的方法。在引用方法时,它可以用来替换 Lambda 表达式。
//例如:如果使用 Lambda 表达式: number -> System.out.println(number ) //那么相应的方法引用如下: System.out::println
其中::是区分类名和方法名的运算符。
面试题11:解释以下代码含义
String:: Valueof表达式
答:是对String类的ValueOf 方法的静态方法引用。System.out::println 是对 System 类的 out 对象的 println 方法的静态方法引用。它返回所传递参数的相应字符串表示形式。参数可以是字符、整数、布尔值等。
面试题12:什么是Stream API?为什么我们需要 Stream API?
答: Stream API 是 Java 8 中添加的新功能。它是一个特殊的类,用于处理来自 Collection 等数据源的对象。
我们需要 Stream API,因为:
- 它支持聚合操作,使处理变得简单。
- 它支持函数式编程。
- 它的处理速度更快。因此,它易于获得更好的性能。
- 它允许并行操作。
面试题13: Java 8 中的 limit() 方法的目的是什么?
答: Stream.limit() 方法指定元素的限制。您在 limit(X) 中指定的大小,它将返回大小为“X”的 Stream。它是 java.util.stream.Stream 的一个方法
面试题14:limit和skip有什么区别?
答: limit() 方法用于返回指定大小的Stream。例如, 如果您提到了 limit(5),那么输出元素的数量将为 5。让我们考虑以下示例。此处的输出返回六个元素,因为限制设置为“6”。
import java.util.stream.Stream;
public class Java8 {
public static void main(String[] args) {
Stream.of(0,1,2,3,4,5,6,7,8)
.limit(6)
/*limit is set to 6, hence it will print the
numbers starting from 0 to 5
*/
.forEach(num->System.out.print("\n"+num));
}
}
//输出0 1 2 3 4 5
而 skip() 方法用于跳过元素。让我们考虑以下示例。在输出中,元素是 6、7、8,这意味着它已经跳过元素直到第 6 个索引(从 1 开始)。
import java.util.stream.Stream;
public class Java8 {
public static void main(String[] args) {
Stream.of(0,1,2,3,4,5,6,7,8)
.skip(6)
/*
It will skip till 6th index. Hence 7th, 8th and 9th
index elements will be printed
*/
.forEach(num->System.out.print("\n"+num));
}
}
//输出6 7 8
面试题15:你将如何使用 Java 8 日期和时间 API 获取当前日期和时间?
答:下面的程序是借助 Java 8 中引入的新 API 编写的。我们使用了 LocalDate、LocalTime 和 LocalDateTime API 来获取当前日期和时间。
在第一个和第二个打印语句中,我们从系统时钟中检索了当前日期和时间,并将时区设置为默认值。在第三个打印语句中,我们使用了 LocalDateTime API,它将打印日期和时间。
class Java8 {
public static void main(String[] args) {
System.out.println("Current Local Date: " + java.time.LocalDate.now());
//Used LocalDate API to get the date
System.out.println("Current Local Time: " + java.time.LocalTime.now());
//Used LocalTime API to get the time
System.out.println("Current Local Date and Time: " + java.time.LocalDateTime.now());
//Used LocalDateTime API to get both date and time
}
}
面试题16: 在 Java 8 中使用 forEach 编写一个程序来打印 5 个随机数?
答:下面的程序在 Java 8 中借助 forEach 生成 5 个随机数。您可以根据要生成的随机数的数量将限制变量设置为任意数字。
import java.util.Random;
class Java8 {
public static void main(String[] args) {
Random random = new Random();
random.ints().limit(5).forEach(System.out::println);
/* limit is set to 5 which means only 5 numbers will be printed
with the help of terminal operation forEach
*/
}
}
面试题17:编写一个程序,在 Java 8 中使用 forEach 按排序顺序打印 5 个随机数?
答:下面的程序在 Java 8 中借助 forEach 生成 5 个随机数。您可以根据要生成的随机数的数量将限制变量设置为任意数字。您唯一需要在此处添加的是 sorted() 方法。
import java.util.Random;
class Java8 {
public static void main(String[] args) {
Random random = new Random();
random.ints().limit(5).sorted().forEach(System.out::println);
/* sorted() method is used to sort the output after
terminal operation forEach
*/
}
}
面试题18: 编写一个 Java 8 程序来获取list集合中所有数字的总和?
答:在这个程序中,我们使用 ArrayList 来存储元素。然后,在 sum() 方法的帮助下,我们计算了 ArrayList 中存在的所有元素的总和。然后将其转换为 Stream 并在 mapToInt() 和 sum() 方法的帮助下添加每个元素。
import java.util.*;
class Java8 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add(50);
// Added the numbers into Arraylist
System.out.println(sum(list));
}
public static int sum(ArrayList<Integer> list) {
return list.stream().mapToInt(i -> i).sum();
// Found the total using sum() method after
// converting it into Stream
}
}
面试题19: 编写一个 Java 8 程序对数字集合进行平方,然后过滤掉大于 100 的数字,然后求剩余数字的平均值?
答:在这个程序中,我们采用了一个整数数组并将它们存储在一个列表中。然后在 mapToInt() 的帮助下,我们对元素进行平方并过滤掉大于 100 的数字。最后,计算剩余数字(大于 100)的平均值。
import java.util.Arrays;
import java.util.List;
import java.util.OptionalDouble;
public class Java8 {
public static void main(String[] args) {
Integer[] arr = new Integer[] { 100, 100, 9, 8, 200 };
List<Integer> list = Arrays.asList(arr);
// Stored the array as list
OptionalDouble avg = list.stream().mapToInt(n -> n * n).filter(n -> n > 100).average();
/* Converted it into Stream and filtered out the numbers
which are greater than 100. Finally calculated the average
*/
if (avg.isPresent())
System.out.println(avg.getAsDouble());
}
}
面试题20: Stream 的 findFirst() 和 findAny() 有什么区别?
答:顾名思义,findFirst() 方法用于从流中查找第一个元素,而 findAny() 方法用于从流中查找任何元素。findFirst() 本质上是预定论,而 findAny() 是非确定性的。在编程中,确定性意味着输出基于系统的输入或初始状态。
面试题21: Iterator 和 Spliterator 有什么区别?
面试题22:什么是Consumer 功能接口?
答:Consumer 函数接口也是单参数接口(如 Predicate
在下面的程序中,我们使用了 accept 方法来检索 String 对象的值。
import java.util.function.Consumer;
public class Java8 {
public static void main(String[] args)
Consumer<String> str = str1 -> System.out.println(str1);
str.accept("Saket");
/* We have used accept() method to get the
value of the String Object
*/
}
}
面试题23:什么是Supplier功能接口?
答:Supplier功能接口不接受输入参数。它属于 java.util.function.Supplier。这将使用 get 方法返回值。在下面的程序中,我们使用了 get 方法来检索 String 对象的值。
import java.util.function.Supplier;
public class Java8 {
public static void main(String[] args) {
Supplier<String> str = () -> "Saket";
System.out.println(str.get());
/* We have used get() method to retrieve the
value of String object str.
*/
}
}
面试题24: Java 8 中的 Nashorn 是什么?
答: Java 8 中的 Nashorn 是一个基于 Java 的引擎,用于执行和评估 JavaScript 代码。
面试题25: Map 和 flatMap 流操作有什么区别?
答: Map Stream 操作为每个输入值提供一个输出值,而 flatMap Stream 操作为每个输入值提供零个或多个输出值。
面试题26: Java 8 中的 MetaSpace 是什么?
答:在 Java 8 中,引入了一个新特性来存储类。存储在 Java 8 中的所有类的区域称为 MetaSpace。MetaSpace 已取代 PermGen。
在 Java 7 之前,Java 虚拟机使用 PermGen 来存储类。由于 MetaSpace 是动态的,因为它可以动态增长并且没有任何大小限制,Java 8 用 MetaSpace 取代了 PermGen。
面试题26: 什么是 JJS?
答: JJS 是一个命令行工具,用于在控制台执行 JavaScript 代码。在 Java 8 中,JJS 是新的可执行文件,它是一个 JavaScript 引擎。
面试题27:解释 Java 8 中的 StringJoiner 类?我们如何使用 StringJoiner 类实现连接多个字符串?
答:在 Java 8 中,包 java.util 中引入了一个新类,称为 StringJoiner。通过这个类,我们可以连接多个由分隔符分隔的字符串,并为它们提供前缀和后缀。
在下面的程序中,我们将学习如何使用 StringJoiner 类连接多个字符串。在这里,我们将“,”作为两个不同字符串之间的分隔符。然后我们在 add() 方法的帮助下添加了五个不同的字符串。最后,打印 String Joiner。
import java.util.StringJoiner;
public class Java8 {
public static void main(String[] args) {
StringJoiner stj = new StringJoiner(",");
// Separated the elements with a comma in between.
stj.add("Saket");
stj.add("John");
stj.add("Franklin");
stj.add("Ricky");
stj.add("Trevor");
// Added elements into StringJoiner “stj”
System.out.println(stj);
}
}
面试题28:编写一个 Java 8 程序来删除集合中的重复元素?
答:在这个程序中,我们将元素存储到一个数组中,并将它们转换为一个列表。此后,我们使用了流并在“Collectors.toSet()”方法的帮助下将其收集到“Set”。
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class Java8 {
public static void main(String[] args) {
Integer[] arr1 = new Integer[] { 1, 9, 8, 7, 7, 8, 9 };
List<Integer> listdup = Arrays.asList(arr1);
// Converted the Array of type Integer into List
Set<Integer> setNoDups = listdup.stream().collect(Collectors.toSet());
// Converted the List into Stream and collected it to “Set”
// Set won't allow any duplicates
setNoDups.forEach((i) -> System.out.print(" " + i));
}
}
面试题29: 编写一个 Java 8 程序来连接两个 Stream?
答:在这个程序中,我们从两个已经创建的列表中创建了两个 Stream,然后使用 concat() 方法将它们连接起来,其中两个列表作为参数传递。最后,打印连接流的元素。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Java8 {
public static void main(String[] args) {
List<String> list1 = Arrays.asList("Java", "8");
List<String> list2 = Arrays.asList("explained", "through", "programs");
Stream<String> concatStream = Stream.concat(list1.stream(), list2.stream());
// Concatenated the list1 and list2 by converting them into Stream
concatStream.forEach(str -> System.out.print(str + " "));
// Printed the Concatenated Stream
}
}
面试题30: 编写一个 Java 8 程序来查找长度大于 5 的列表中的字符串数?
答:在这个程序中,使用 add() 方法将四个字符串添加到列表中,然后借助 Stream 和 Lambda 表达式,我们统计了长度大于 5 的字符串。
import java.util.ArrayList;
import java.util.List;
public class Java8 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Saket");
list.add("Saurav");
list.add("Softwaretestinghelp");
list.add("Steve");
// Added elements into the List
long count = list.stream().filter(str -> str.length() > 5).count();
/* Converted the list into Stream and filtering out
the Strings whose length more than 5
and counted the length
*/
System.out.println("We have " + count + " strings with length greater than 5");
}
}
总结
以上就是30个最常见的Java8面试题及答案整理,你学会了吗?






