Java8 面试题

亲爱的读者,这些 Java8 面试问题是专门设计的,目的是让您熟悉在Java8 语言主题的面试中可能遇到的问题。 根据我的经验,优秀的面试官几乎不打算在你的面试中问任何特定的问题,通常问题从主题的一些基本概念开始,然后他们根据进一步的讨论和你的回答继续 −

Java8引入了哪些新特性?

Java8 添加了数十个功能,最重要的功能如下所述 −

  • Lambda 表达式 − 向 Java 添加功能处理能力。

  • 方法引用 − 通过名称引用函数而不是直接调用它们。 使用函数作为参数。

  • 默认方法 − 具有默认方法实现的接口。

  • 新工具 − 添加了新的编译器工具和实用程序,例如"jdeps"以找出依赖关系。

  • Stream API − 促进 Stream 流处理的新流 API。

  • 日期时间API − 改进的日期时间 API。

  • Optional − 强调正确处理空值的最佳实践。

  • Nashorn,JavaScript 引擎 − 基于 Java 的引擎,用于执行 JavaScript 代码。

除了这些新功能外,在编译器和 JVM 级别都在后台完成了许多功能增强。

您将如何使用 Java8 lambda 表达式对字符串列表进行排序?

以下代码使用 Java8 lambda 表达式对字符串列表进行排序:

//sort using Java8
private void sortUsingJava8(List<String> names) {
  Collections.sort(names, (s1, s2) -> s1.compareTo(s2));
}

Java8 lambda 表达式有哪些特点?

lambda 表达式具有以下语法特征 -

parameter −> expression body

以下是 lambda 表达式的重要特征 −

  • 可选类型声明 − 无需声明参数的类型。 编译器可以从参数的值中推断出相同的内容。

  • 可选的参数两边的括号 − 无需在括号中声明单个参数。 对于多个参数,需要括号。

  • 可选的大括号 − 如果正文包含单个语句,则无需在表达式正文中使用花括号。

  • 可选的返回关键字 − 如果主体只有一个表达式来返回值,编译器会自动返回值。 需要花括号来指示表达式返回一个值。

为什么要使用 lambda 表达式?

Lambda 表达式主要用于定义功能接口的内联实现,即仅具有单个方法的接口。 在上面的示例中,我们使用了各种类型的 lambda 表达式来定义 MathOperation 接口的操作方法。 然后我们定义了GreetingService的sayMessage的实现。

Lambda 表达式消除了匿名类的需要,并为 Java 提供了非常简单但功能强大的函数式编程能力。

你可以在 lambda 表达式中访问什么样的变量??

使用 lambda 表达式,您可以引用 final 变量或有效的 final 变量(仅分配一次)。 如果第二次为变量赋值,Lambda 表达式会引发编译错误。

什么是方法引用?

方法引用有助于通过名称指向方法。 使用 ::(双冒号)符号描述方法引用。 方法引用可用于指向以下类型的方法 −

  • 静态方法

  • 实例方法

  • 使用 new 运算符的构造函数 (TreeSet::new)

解释 System.out::println 表达式。

System.out::println方法是对System类out对象的println方法的静态方法引用。

什么是功能接口?

功能接口具有单一的功能来展示。 例如,具有单一方法"compareTo"的 Comparable 接口用于比较目的。 Java8 定义了很多功能接口,广泛用于 lambda 表达式。

BiConsumer<T,U> 功能接口的用途是什么?

它表示接受两个输入参数并且不返回任何结果的操作。

BiFunction<T,U,R> 功能接口的作用是什么?

它表示接受两个参数并产生结果的函数。

BinaryOperator<T> 功能接口的作用是什么?

它表示对两个相同类型的操作数进行操作,产生与操作数相同类型的结果。

BiPredicate<T,U> 功能接口的作用是什么?

它表示两个参数的谓词(布尔值函数)。

BooleanSupplier 功能接口的用途是什么?

它代表布尔值结果的提供者。

Consumer<T> 功能接口的作用是什么?

它表示接受单个输入参数并且不返回任何结果的操作。

DoubleBinaryOperator 功能接口的用途是什么?

它表示对两个双值操作数进行运算并产生双值结果。

DoubleConsumer功能接口的作用是什么?

它表示接受单个双值参数且不返回任何结果的操作。

DoubleFunction<R> 功能接口的作用是什么?

它表示接受双值参数并产生结果的函数。

DoublePredicate功能接口的作用是什么?

它表示一个双值参数的谓词(布尔值函数)。

DoubleSupplier 功能接口的作用是什么?

它代表双值结果的供应商。

DoubleToIntFunction 功能接口的用途是什么?

它表示一个接受双值参数并产生 int 值结果的函数。

DoubleToLongFunction 功能接口的用途是什么?

它表示一个接受双值参数并产生长值结果的函数。

DoubleUnaryOperator功能接口的作用是什么?

它表示对产生双值结果的单个双值操作数的操作。

Function<T,R> 功能接口的作用是什么?

它表示接受一个参数并产生结果的函数。

IntBinaryOperator 函数接口的作用是什么?

它表示对两个 int 值操作数的操作并产生一个 int 值结果。

IntConsumer函数接口的作用是什么?

它表示接受单个 int 值参数且不返回任何结果的操作。

IntFunction<R> 功能接口的作用是什么?

它表示一个接受 int 值参数并产生结果的函数。

IntPredicate 功能接口的用途是什么?

它表示一个 int 值参数的谓词(布尔值函数)。

IntSupplier 功能接口的用途是什么?

它代表整数值结果的提供者。

IntToDoubleFunction 功能接口的用途是什么?

它表示一个接受 int 值参数并产生双值结果的函数。

IntToLongFunction 功能接口的用途是什么?

它表示一个函数,该函数接受一个 int 值参数并产生一个 long 值结果。

IntUnaryOperator功能接口的作用是什么?

它表示对单个 int 值操作数的操作,该操作产生 int 值结果。

LongBinaryOperator 功能接口的用途是什么?

它表示对两个长值操作数的操作并产生一个长值结果。

LongConsumer功能接口的作用是什么?

它表示接受单个长值参数并且不返回任何结果的操作。

LongFunction<R> 功能接口的作用是什么?

它表示一个接受长值参数并产生结果的函数。

LongPredicate 功能接口的用途是什么?

它表示一个长值参数的谓词(布尔值函数)。

LongSupplier 功能接口的作用是什么?

它代表长期价值结果的供应商。

LongToDoubleFunction 功能接口的用途是什么?

它表示一个接受长值参数并产生双值结果的函数。

LongToIntFunction 功能接口的用途是什么?

它代表一个接受长值参数并产生一个整型值结果的函数。

LongUnaryOperator 功能接口的用途是什么?

它表示对产生长值结果的单个长值操作数的操作。

ObjDoubleConsumer<T> 功能接口的作用是什么?

它表示接受对象值和双值参数的操作,并且不返回任何结果。

ObjIntConsumer<T> 功能接口的作用是什么?

它表示接受对象值和整数值参数的操作,并且不返回任何结果。

ObjLongConsumer<T> 功能接口的作用是什么?

它表示接受对象值和长值参数并且不返回任何结果的操作。

Predicate<T> 功能接口的作用是什么?

它表示一个参数的谓词(布尔值函数)。

Supplier<T> 功能接口的作用是什么?

它代表结果的提供者。

ToDoubleBiFunction<T,U> 功能接口的作用是什么?

它表示接受两个参数并产生双值结果的函数。

ToDoubleFunction<T> 功能接口的作用是什么?

它表示一个产生双值结果的函数。

ToIntBiFunction<T,U> 功能接口的作用是什么?

它表示一个接受两个参数并产生一个 int 值结果的函数。

ToIntFunction<T> 功能接口的作用是什么?

它代表一个函数,它产生一个 int 值的结果。

ToLongBiFunction<T,U> 功能接口的作用是什么?

它表示一个接受两个参数并产生长值结果的函数。

ToLongFunction<T> 功能接口的作用是什么?

它表示一个产生长值结果的函数。

UnaryOperator<T> 功能接口的作用是什么?

它表示对单个操作数的操作,产生与其操作数类型相同的结果。

什么是 default 默认方法?

在 Java8 中,接口可以在接口中具有函数的默认实现。

什么是静态 default 默认方法?

从 Java8 开始,接口也可以有静态辅助方法。

public interface vehicle {
   default void print() {
      System.out.println("I am a vehicle!");
   }
 
   static void blowHorn() {
      System.out.println("Blowing horn!!!");
   }
}

如何调用类中接口的默认方法?

使用 super 关键字和接口名称。

interface Vehicle {
   default void print() {
      System.out.println("I am a vehicle!");
   }
}
class Car implements Vehicle {
   public void print() {
      Vehicle.super.print();                  
   }
}

如何调用类中接口的静态方法?

使用接口名称。

interface Vehicle {
   static void blowHorn() {
      System.out.println("Blowing horn!!!");
   }
}
class Car implements Vehicle {
   public void print() {
      Vehicle.blowHorn();                  
   }
}

什么是 Java8 中的 Stream 流?

Stream 表示来自源的一系列对象,它支持聚合操作。

Java8 中的流操作是什么?

大多数流操作返回流本身,以便可以对它们的结果进行流水线处理。 这些操作称为中间操作,它们的功能是获取输入、处理它们并将输出返回给目标。 collect() 方法是一个终端操作,通常出现在流水线操作的末尾,以标记流的结束。

Java8中Collections和Stream有什么区别?

与需要显式迭代的集合相比,流操作在提供的源元素上进行内部迭代。

Java8中stream的forEach方法的作用是什么?

Stream 提供了一个新方法"forEach"来迭代流中的每个元素。

如何使用 Java8 的 forEach 打印 10 个随机数?

以下代码段显示如何使用 forEach 打印 10 个随机数。

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

Java8中stream的map方法有什么用?

'map' 方法用于将每个元素映射到其对应的结果。

如何在 Java8 中打印唯一的数字平方?

以下代码段使用 map 打印唯一的数字方块。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
//get list of unique squares
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

Java8中stream的filter方法有什么用?

'filter' 方法用于根据条件消除元素。

如何在 Java8 中打印空字符串的数量?

以下代码段使用过滤器打印空字符串的计数。

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
//get count of empty string
int count = strings.stream().filter(string −> string.isEmpty()).count();

Java8中stream的limit方法有什么用?

'limit' 方法用于减小流的大小。

如何在 Java8 中打印 10 个随机数?

以下代码段显示如何打印 10 个随机数。

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

Java8中stream的sorted方法有什么用?

'sorted' 方法用于对流进行排序。

如何在 Java8 中按排序顺序打印 10 个随机数?

以下代码段显示如何按排序顺序打印 10 个随机数。

Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);

Java8 中的并行处理是什么?

parallelStream 是用于并行处理的流的替代方案。 查看以下使用 parallelStream 打印空字符串计数的代码段。

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
//get count of empty string
int count = strings.parallelStream().filter(string −> string.isEmpty()).count();
//It is very easy to switch between sequential and parallel streams.

Java8 中的收集器是什么?

收集器用于组合流元素的处理结果。 收集器可用于返回列表或字符串。

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("Filtered List: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("Merged String: " + mergedString);

Java8 中的统计信息收集器是什么?

在 Java8 中,引入了统计信息收集器,以在进行流处理时计算所有统计信息。

如何使用 Java8 获得列表中出现的最大数字?

以下代码将打印列表中存在的最大数字。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = integers.stream().mapToInt((x) −> x).summaryStatistics();
System.out.println("Highest number in List : " + stats.getMax());

如何使用 Java8 获得列表中出现的最小数字?

以下代码将打印列表中存在的最大数字。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = integers.stream().mapToInt((x) −> x).summaryStatistics();
System.out.println("Lowest number in List : " + stats.getMin());

如何使用 Java8 获取列表中所有数字的总和?

以下代码将打印列表中所有数字的总和。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = integers.stream().mapToInt((x) −> x).summaryStatistics();
System.out.println("Sum of all numbers : " + stats.getSum());

如何使用 Java8 获取列表中所有数字的平均值?

以下代码将打印列表中所有数字的平均值。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = integers.stream().mapToInt((x) −> x).summaryStatistics();
System.out.println("Average of all numbers : " + stats.getAverage());

Java8 中的 Optional 是什么?

Optional 是一个容器对象,用于包含非空对象。 可选对象用于表示没有值的 null。 此类具有各种实用方法,以方便代码将值处理为"可用"或"不可用",而不是检查空值。 它是在 Java8 中引入的,类似于 Guava 中的 Optional。

Java8中的Nashorn是什么?

在 Java8 中,Nashorn 引入了一个大大改进的 javascript 引擎,以取代现有的 Rhino。 Nashorn 提供了 2 到 10 倍的性能提升,因为它直接在内存中编译代码并将字节码传递给 JVM。 Nashorn 使用 Java 7 中引入的 invokedynamics 功能来提高性能。

JAVA8中的jjs是什么?

对于 Nashorn 引擎,Java8 引入了一个新的命令行工具 jjs,用于在控制台执行 javascript 代码。

你能从 Java8 代码库执行 javascript 代码吗?

是的! 使用 ScriptEngineManager,可以在 Java 中调用和解释 JavaScript 代码。

JAVA8 中的本地日期时间 API 是什么?

Local − 简化的日期时间 API,没有复杂的时区处理。

什么是 JAVA8 中的分区日期时间 API?

Zoned − 专门的日期时间 API 来处理各种时区。

java8 中的 chromounits 是什么?

java.time.temporal.ChronoUnit 枚举是在 Java8 中添加的,用于替换旧 API 中使用的整数值来表示日、月等。

如何使用 java8 的本地 datetime api 获取当前日期?

以下代码使用本地日期时间 api 获取当前日期 −

//Get the current date
LocalDate today = LocalDate.now();
System.out.println("Current date: " + today);

如何使用 java8 的本地 datetime api 将 1 周添加到当前日期?

以下代码使用本地日期时间 api 将 1 周添加到当前日期 −

//add 1 week to the current date
LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
System.out.println("Next week: " + nextWeek);

如何使用 java8 的本地 datetime api 将 1 个月添加到当前日期?

以下代码使用本地日期时间 api 将 1 个月添加到当前日期:

//add 1 month to the current date
LocalDate today = LocalDate.now();
LocalDate nextMonth = today.plus(1, ChronoUnit.MONTHS);
System.out.println("Next month: " + nextMonth);

如何使用 java8 的本地 datetime api 将当前日期增加 1 年?

以下代码使用本地日期时间 api 将 1 年添加到当前日期 −

//add 1 year to the current date
LocalDate today = LocalDate.now();
LocalDate nextYear = today.plus(1, ChronoUnit.YEARS);
System.out.println("Next year: " + nextYear);

如何使用 java8 的本地 datetime api 将 10 年添加到当前日期?

以下代码使用本地日期时间 api 将 10 年添加到当前日期 −

//add 10 years to the current date
LocalDate today = LocalDate.now();
LocalDate nextDecade = today.plus(1, ChronoUnit.DECADES);
System.out.println("Date after ten year: " + nextDecade);

你将如何使用 java8 获得下周二?

以下代码使用 java8 获取下周二 −

//get the next tuesday
LocalDate today = LocalDate.now();
LocalDate nextTuesday = today.with(TemporalAdjusters.next(DayOfWeek.TUESDAY));
System.out.println("Next Tuesday on : " + nextTuesday);

如何使用 java8 获取下个月的第二个星期六?

以下代码使用 java8 获取下个月的第二个星期六 −

//get the second saturday of next month
LocalDate firstInYear = LocalDate.of(date1.getYear(),date1.getMonth(), 1);
LocalDate secondSaturday = firstInYear.with(TemporalAdjusters.nextOrSame(DayOfWeek.SATURDAY)).with(TemporalAdjusters.next(DayOfWeek.SATURDAY));
System.out.println("Second Saturday on : " + secondSaturday);

如何使用 java8 以毫秒为单位获取当前日期的瞬间?

以下代码以毫秒为单位获取当前日期的瞬间 −

//Get the instant of current date in terms of milliseconds
Instant now = currentDate.toInstant();

如何使用 java8 以毫秒为单位获取本地日期时间的瞬间?

以下代码使用以毫秒为单位的时间获取本地日期时间的瞬间 −

Instant now = currentDate.toInstant();
ZoneId currentZone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(now, currentZone);
System.out.println("Local date: " + localDateTime);

如何使用 java8 以毫秒为单位获取分区日期时间的瞬间?

以下代码使用以毫秒为单位的时间获取分区日期时间的瞬间 −

Instant now = currentDate.toInstant();
ZoneId currentZone = ZoneId.systemDefault();
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(now, currentZone);
System.out.println("Zoned date: " + zonedDateTime);

哪个类实现了Java8中使用Base64编码方案对字节数据进行解码的解码器?

static class Base64.Decoder − 此类使用 RFC 4648 和 RFC 2045 中指定的 Base64 编码方案实现解码字节数据的解码器。

哪个类实现了Java8中使用Base64编码方案对字节数据进行编码的编码器?

static class Base64.Encoder − 此类使用 RFC 4648 和 RFC 2045 中指定的 Base64 编码方案实现编码字节数据的编码器。

你将如何创建 Base64 解码器?

Base64 类的 getDecoder() 方法返回一个使用 Basic 类型 base64 编码方案解码的 Base64.Decoder。

你将如何创建 Base64 编码器?

Base64 类的 getEncoder() 方法返回使用 Basic 类型 base64 编码方案进行编码的 Base64.Encoder。

您将如何创建使用 MIME 类型 base64 编码方案进行解码的 Base64 解码器?

Base64 类的 getMimeDecoder() 方法返回一个使用 MIME 类型 base64 解码方案解码的 Base64.Decoder。

您将如何创建使用 MIME 类型 base64 编码方案进行编码的 Base64 编码器?

Base64 类的 getMimeEncoder() 方法返回使用 MIME 类型 base64 编码方案进行编码的 Base64.Encoder。

您将如何创建使用 URL 和文件名安全类型 base64 编码方案进行解码的 Base64 解码器?

Base64 类的 getUrlDecoder() 方法返回一个 Base64.Decoder,它使用 URL 和文件名安全类型 base64 编码方案进行解码。

您将如何创建使用 URL 和文件名安全类型 base64 编码方案进行编码的 Base64 编码器?

Base64 类的 getUrlEncoder() 方法返回一个使用 URL 和文件名安全类型 base64 编码方案进行编码的 Base64.Encoder。