Java 最初是从 Oak 语言演变而来的,诞生于 1996 年初,其主要版本为 Java 1 或 JDK 1.0。Java 最初是由 Sun Microsystems 的 James Gosling 爵士设计和开发的。Java 8 或 JDK 8.0 是 2014 年 Java 编程语言的主要版本之一。它也被称为代号 Spider。Java 是一个开源项目,目前由 Oracle Corporation 管理。
Java 8常见面试题有哪些?本文将带你了解 Java 8 面试问题,适用于新人和有经验的人、范围和机会。
基本的Java 8常见面试题合集
1. 描述一下Java 8 新增的特性?
以下是 Java 8 的新增功能:
功能名称 | 描述 |
---|---|
Lambda 表达式 | 可以共享或称为对象的函数。 |
函数接口 | 单一抽象方法接口。 |
方法参考 | 使用函数作为参数来调用方法。 |
默认方法 | 它提供了接口内方法的实现,支持“接口进化”设施。 |
Stream API | 提供数据管道处理的抽象层。 |
日期时间 API | 新改进的 joda-time 启发式 API 克服了以前版本中的缺点 |
Optional | 用于检查空值的包装类,并有助于根据该值进行进一步处理。 |
Rhino,JavaScript 引擎 | JavaScript 引擎的临时版本,可以在 Java 中执行 JavaScript,以取代 Rhino。 |
2. Java 8面试题解析:Java 8 属于哪种编程范式?
- 面向对象的编程语言。
- 函数式编程语言。
- 过程编程语言。
- 逻辑编程语言
3. Java 8 的显着优势是什么?
- 紧凑、可读和可重用的代码。
- 更少的样板代码。
- 并行操作和执行。
- 可以跨操作系统移植。
- 高稳定性。
- 稳定的环境。
- 足够的支持
4. 什么是元空间?它与 PermGen 有何不同?
PremGen: Java 8 之前,类的元数据信息存储在 PremGen(Permanent-Generation)内存类型中。PremGen 大小固定,不能动态调整大小。它是一个连续的 Java 堆内存。
MetaSpace: Java 8 将类的元数据存储在称为“MetaSpace”的本机内存中。它不是连续的堆内存,因此可以动态增长,这有助于克服大小限制。这改进了元数据的垃圾收集、自动调整和取消分配。
5. 什么是功能或 SAM 接口?
函数式接口是只有一个抽象方法的接口。因此,它也被称为单一抽象方法 (SAM) 接口。它被称为函数式接口,因为它将函数包装为接口,或者换句话说,函数由接口的单个抽象方法表示。
函数式接口可以有任意数量的默认、静态和覆盖方法。对于声明功能接口@FunctionalInterface 注释是可选的。如果此注解用于具有多个抽象方法的接口,则会产生编译器错误。
@FunctionalInterface // Annotation is optional
public interface Foo() {
// Default Method - Optional can be 0 or more
public default String HelloWorld() {
return "Hello World";
}
// Static Method - Optional can be 0 or more
public static String CustomMessage(String msg) {
return msg;
}
// Single Abstract Method
public void bar();
}
public class FooImplementation implements Foo {
// Default Method - Optional to Override
@Override
public default String HelloWorld() {
return "Hello Java 8";
}
// Method Override
@Override
public void bar() {
System.out.println(“Hello World”);
}
}
public static void main(String[] args) {
FooImplementation fi = new FooImplementation();
System.out.println(fi.HelloWorld());
System.out.println(fi.CustomMessage(“Hi”));
fi.bar();
}
6. 一个函数接口可以扩展/继承另一个接口吗?
函数接口不能使用抽象方法扩展另一个接口,因为它会使每个函数接口一个抽象方法的规则无效。例如:
interface Parent {
public int parentMethod();
}
@FunctionalInterface // This cannot be FunctionalInterface
interface Child extends Parent {
public int childMethod();
// It will also extend the abstract method of the Parent Interface
// Hence it will have more than one abstract method
// And will give a compiler error
}
它可以扩展其他没有任何抽象方法而只有默认、静态、另一个类被覆盖和普通方法的接口。例如:
interface Parent {
public void parentMethod(){
System.out.println("Hello");
}
}
@FunctionalInterface
interface Child extends Parent {
public int childMethod();
}
7. 什么是默认方法,为什么需要它?
Java 8面试题解析:接口中具有预定义主体的方法称为默认方法。它使用关键字 default。Java 8 中引入了默认方法,以便在 JDK 修改任何接口的情况下具有“向后兼容性”。如果将新的抽象方法添加到接口中,则实现该接口的所有类都将中断,并且必须实现新方法。使用默认方法,不会对实现类的接口产生任何影响。如果在实现中需要,可以覆盖默认方法。此外,它不符合同步或最终的条件。
@FunctionalInterface // Annotation is optional
public interface Foo() {
// Default Method - Optional can be 0 or more
public default String HelloWorld() {
return "Hello World";
}
// Single Abstract Method
public void bar();
}
8. 接口中的静态方法是什么?
包含方法实现的静态方法由接口拥有并使用接口名称调用,适用于定义实用方法且不能被覆盖。
9. 有哪些标准的 Java 预定义功能接口?
以前 Java 版本中一些著名的预定义功能接口是 Runnable、Callable、Comparator 和 Comparable。Java 8 引入了像Supplier、Consumer、Predicate 等函数式接口。Java 8 中引入的其他预定义函数式接口及其描述请参考java.util.function 文档。
Runnable:用于在另一个线程上执行一个类的实例,没有参数和返回值。
Callable:用于在另一个线程上执行一个类的实例,没有参数,它要么返回一个值,要么抛出一个异常。
Comparator:用于按照用户定义的顺序对不同的对象进行排序
Comparable:用于按自然排序顺序对对象进行排序
10. Java 8常见面试题有哪些:预定义功能接口有哪些种类?
Function:将参数转换为可返回值。
Predicate:执行测试并返回布尔值。
Consumer:接受参数但不返回任何值。
Supplier:不接受任何参数但返回一个值。
Operator:执行接受相同输入类型的归约类型操作。
11. 什么是 Java 中的 lambda 表达式以及 lambda 表达式与函数式接口有什么关系?
Lambda 表达式是一种没有名称的函数。它可能有也可能没有结果和参数。它被称为匿名函数,因为它本身没有类型信息。它是按需执行的。它有利于从集合中迭代、过滤和提取数据。
由于 lambda 表达式类似于匿名函数,因此它们只能应用于函数式接口的单个抽象方法。它将从函数接口的抽象方法的签名中推断出返回类型、类型和几个参数。
高级Java 8常见面试题合集
12. lambda 表达式的基本结构/语法是什么?
FunctionalInterface fi = (String name) -> {
System.out.println("Hello "+name);
return "Hello "+name;
}
Lambda 表达式可以分为三个不同的部分,如下所示:
1. 参数/参数列表:
(字符串名称)
参数列表在 () 圆括号中传递。它可以有零个或多个参数。声明参数的类型是可选的,可以根据上下文推断。
2. 箭头标记:
->
箭头标记被称为 lambda 箭头运算符。它用于将参数与正文分开,或者将参数列表指向正文。3. 表情/身体:
{
System.out.println("Hello "+name);
return "Hello "+name;
}
主体可以有表达式或语句。{} 仅当有多于一行时才需要大括号。在一个语句中,返回类型与语句的返回类型相同。在其他情况下,返回类型要么由 return 关键字推断,要么由 void 推断(如果没有返回任何内容)。
13. lambda 表达式的特点是什么?
以下是定义为 lambda 表达式的方法的两个重要特征:
- Lambda 表达式可以作为参数传递给另一个方法。
- Lambda 表达式可以是独立的,不属于任何类。
14.什么是类型接口?
甚至在 Java 的早期版本中也可以使用类型接口。用于编译器在编译时通过查看方法调用和相应声明来推断参数的类型。
15. lambda 表达式的类型和常用方法有哪些?
lambda 表达式本身没有任何特定类型。一个 lambda 表达式一旦被分配给一个函数式接口就接收类型。相同的 lambda 表达式可以分配给不同的功能接口类型,并且可以具有不同的类型。
例如,考虑表达式 s -> s.isEmpty() :
Predicate<String> stringPredicate = s -> s.isEmpty();
Predicate<List> listPredicate = s -> s.isEmpty();
Function<String, Boolean> func = s -> s.isEmpty();
Consumer<String> stringConsumer = s -> s.isEmpty();
表达式的常用方法
分配给函数式接口 —>Predicate<String> stringPredicate = s -> s.isEmpty();
可以作为具有函数式类型的参数传递 —>stream.filter(s -> s.isEmpty())
从函数中返回它 —>return s -> s.isEmpty()
将其转换为函数式类型 —>(Predicate<String>) s -> s.isEmpty()
16.在Java 8中,什么是方法引用?
方法引用是引用函数接口方法的一种紧凑方式。它用于引用一个方法而不调用它。::(双冒号)用于描述方法引用。语法是class::methodName
例如:
Integer::parseInt(str) \\
方法参考
str -> Integer.ParseInt(str); \\
等价的 lambda
17. String::ValueOf 表达式是什么意思?
它是对 String 类的 Valueof() 方法的静态方法引用。它将返回传递的参数的字符串表示形式。
18. 什么是可选类?
Java 8面试题解析:可选的是一个容器类型,它可能包含也可能不包含值,即零(空)或一个(非空)值。它是 java.util 包的一部分。有一些预定义的方法,如 isPresent(),如果值存在,则返回 true,否则返回 false;方法 get(),如果存在则返回值。
static Optional<String> changeCase(String word) {
if (name != null && word.startsWith("A")) {
return Optional.of(word.toUpperCase());
}
else {
return Optional.ofNullable(word); // someString can be null
}
}
19.使用Optional类有什么好处?
以下是使用 Optional 类的主要优点:
它封装了可选值,即空值或非空值,这有助于避免空检查,从而产生更好、可读和健壮的代码 它充当对象的包装器并返回对象而不是值,这可以用于避免运行时 NullPointerExceptions。
20. 什么是 Java 8 流?
流是一种以声明方式表达数据处理查询的抽象。
Stream 表示一系列数据对象和对该数据的一系列操作,它是一个与 Java I/O 无关的数据管道,Streams 不永久保存任何数据。
关键界面是java.util.stream.Stream<T>
. 它接受函数式接口,以便可以传递 lambda。流支持流畅的接口或链接。下面是基本的流时间线大理石图:
21. Stream 的主要组成部分是什么?
流的组成部分是:
- 一个数据源
- 一组中间操作来处理数据源
- 产生结果的单终端操作
22. Java 8常见面试题有哪些:Stream 可以处理的数据对象的来源是什么?
Stream 可以处理以下数据:
- 数组的集合。
- I/O 通道或输入设备。
- 反应性来源(例如,社交媒体中的评论或推文/转发推文)
- 流生成器函数或静态工厂。
23. 什么是中间和终端操作?
中级操作:
- 处理流元素。
- 通常将一个流转换为另一个流。
- 是惰性的,即在调用终端操作之前不执行。
- 对所有源元素进行内部迭代。
- 可以在处理管道中链接任意数量的操作。
- 按照定义的顺序应用操作。
- 中间操作主要是 lambda 函数。
终端操作:
- 启动 Stream 管道。
- 用于收集处理后的Stream数据。
int count = Stream.of(1, 2, 3, 4, 5)
.filter(i -> i <4) // Intermediate Operation filter
.count(); // Terminal Operation count
24. 最常用的中间操作有哪些?
Filter(Predicate<T>) - 允许有选择地处理 Stream 元素。它返回满足谓词提供的条件的元素。
map(Funtion<T, R>) - 返回一个新的 Stream,通过应用提供的映射器函数来转换每个元素。= sorted() - 对输入元素进行排序,然后将它们传递到下一个阶段。
distinct() - 仅将元素传递到下一阶段,尚未传递。
limit(long maxsize) - 将流大小限制为 maxsize。
skip(long start) - 跳过初始元素直到开始。
peek(Consumer) - 在不修改流的情况下应用消费者。
flatMap(mapper) - 将每个元素转换为其组成元素的流,并将所有流扁平化为单个流。
25、什么是有状态的中间操作?给出一些有状态中间操作的例子。
为了完成一些中间操作,需要维护一些状态,这种中间操作称为有状态中间操作。并行执行这些类型的操作很复杂。
例如: sorted() 、 distinct() 、 limit() 、 skip() 等。
将数据元素发送到管道中的进一步步骤停止,直到所有数据都为 sorted() 排序并且流数据元素存储在临时数据结构中。
26. Java 8常见面试题合集:最常见的终端操作类型是什么?
- collect() - 从流序列的所有元素中收集单个结果。
- reduce() - 从流序列的所有元素产生一个结果
- count() - 返回流中元素的数量。
- min() - 从流中返回 min 元素。
- max() - 从流中返回最大元素。
- 搜索/查询操作
- anyMatch() , noneMatch() , allMatch() , ... - 短路操作。
- 将 Predicate 作为匹配条件的输入。
- 流处理将在可以确定结果时停止。
- 迭代操作
- forEach() - 用于处理每个 Stream 元素。它接受消费者。
- forEachOrdered() - 在并行流中维护顺序很有帮助。
27. findFirst() 和 findAny() 有什么区别?
findFirst() | findAny() |
---|---|
返回流中的第一个元素 | 从流中返回任何元素 |
本质上确定性 | 本质上是不确定的 |
28. Collections 和 Stream 有什么不同?
集合是 Stream 的来源。Java 8 集合 API 得到了增强,默认方法从集合中返回 Stream<T>。
Collections | Streams |
---|---|
数据结构包含所有数据元素 | 不存储任何数据。有能力按需处理无限数量的元素 |
外部迭代 | 内部迭代 |
可以处理任意次数 | 只遍历一次 |
元素易于访问 | 无法直接访问特定元素 |
是数据存储 | 是一个处理数据的API |
29. Java 8 中新的日期和时间 API 有什么特点?
- 不可变类和线程安全
- 时区支持
- 流利的对象创建和算术方法
- 解决了早期 API 的 I18N 问题
- 受流行的 joda-time 包影响
- 所有软件包均基于 ISO-8601 日历系统
30. 新的数据和时间 API 有哪些重要的包?
- 时间
- dates
- times
- Instants
- durations
- time-zones
- periods
- Java.time.format
- Java.time.temporal
- java.time.zone
31. 举例说明 LocalDate、LocalTime 和 LocalDateTime API。
本地日期
- 没有时间分量的日期
- 默认格式 - yyyy-MM-dd (2020-02-20)
- 今天的本地日期 = LocalDate.now(); // 给出今天的日期
- LocalDate aDate = LocalDate.of(2011, 12, 30); //(年、月、日)
当地时间
- 没有日期的纳秒精度时间
- 默认格式 - hh:mm:ss:zzz (12:06:03.015) 纳秒是可选的
- LocalTime now = LocalTime.now(); // 现在给出时间
- LocalTime aTime2 = LocalTime.of(18, 20, 30); //(小时,分钟,秒)
本地日期时间
- 保存日期和时间
- 默认格式 - yyyy-MM-dd-HH-mm-ss.zzz (2020-02-20T12:06:03.015)
- LocalDateTime 时间戳 = LocalDateTime.now(); // 现在给出时间戳
- //(年、月、日、时、分、秒)
- LocalDateTime dt1 = LocalDateTime.of(2011, 12, 30, 18, 20, 30);
32. 在 Java 8 中定义 Nashorn
Java 8面试题解析:Nashorn 是一个与 Java 8 捆绑在一起的 JavaScript 处理引擎。它提供了更好的符合 ECMA(欧洲计算机制造商协会)规范化 JavaScript 规范的能力,并且在运行时性能比旧版本更好。
33、Java 8常见面试题有哪些:JJS在Java 8中有什么用?
作为 Java 8 的一部分,JJS 是一个命令行工具,可帮助在控制台中执行 JavaScript 代码。以下是 CLI 命令的示例:
JAVA>jjs
jjs> print("Hello, Java 8 - I am the new JJS!")
Hello, Java 8 - I am the new JJS!
jjs> quit()
>>
Java 8常见面试题合集结论
总而言之,Java 是一种流行的编程语言,在 TIOBE 和 PYPL 编程语言排名中均位居第二。Twitter、LinkedIn、Amazon、PayPal 等世界领先的科技巨头都使用 Java 来构建他们的 Web 应用程序和后端 Web 系统。Java 也是用于开发 Android 应用程序的主要语言之一;由 Google 支持和推广的操作系统。
截至今天,StackOverflow 上有 1,751,661 个关于 Java 的问题,GitHub 上有 123,776 个 Java 公共存储库,并且还在不断增加。考虑到 Java 8 是最稳定的版本之一,同样有巨大的职业机会和范围。只需了解概念,实施它们并为面试做好准备!