Java面试中的经典10个问题,大厂必备(附精准答案)

本文列举了Java面试中常见的10个问题,涉及函数式接口、@FunctionalInterface、lambda表达式、Stream API和并发等知识点,并详细解答,帮助你更好地准备大厂面试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Java程序员的面试中,经常会被问到类似这样的问题:

  1. Java中的函数式接口是什么意思?
  2. 注解 @FunctionalInterface 的作用是什么?
  3. 实现一个函数式接口有哪几种方式?
  4. lambda表达式和匿名内部类有什么区别?
  5. Java中的方法引用有哪几种形式?
  6. 能说说你对 Stream 接口中的 map 和 reduce 方法的理解吗?
  7. Stream并行编程的底层实现用了什么多线程框架?
  8. 能说说 Stream 并行编程的适用场景以及注意事项吗?
  9. ConcurrentHashMap中,有哪些方法具备原子性?
  10. 为什么在lambda表达式中引用外部变量时,要求外部变量是final的?怎么绕开这个限制?

问题答案

1. Java中的函数式接口是什么意思?

只有一个抽象方法的接口都属于函数式接口。英文术语为 Functional Interface 。

2. 注解 @FunctionalInterface 的作用是什么?

@FunctionalInterface 主要是告诉编译器它修饰的接口是一个函数式接口,如果接口的定义不符合函数式接口的规范,那么在编译阶段就会报错。当然,我们也可以不加这个注解,对代码的使用没有任何影响。

3. 实现一个函数式接口有哪几种方式?

有3种方式:

  • 通过一个类来实现,包括常规的类和匿名内部类
  • 通过lambda表达式来实现
  • 通过方法引用来实现

4. lambda表达式和匿名内部类有什么区别?

匿名内部类本质是一个类,只是不需要程序员显示指定类名,编译器会自动为该类取名。而 lambda 表达式本质是一个函数,当然,编译器也会为它取名。在JVM层面,匿名内部类对应的是一个 class 文件,而 lambda 表达式对应的是它所在主类的一个私有方法。

5. Java中的方法引用有哪几种形式?

有4种形式:

  • object::instanceMethod 对象 + 实例方法
  • ClassName::staticMethod 类名 + 静态方法
  • ClassName::new 类名 + new关键字,构造方法引用
  • ClassName::instanceMethod 类名 + 实例方法

6. 能说说你对 Stream 接口中的 map 和 reduce 方法的理解吗?

map方法的作用是遍历Stream中的每个元素,将每个元素映射为另一个元素。map,来源于数学中的概念函数映射。

reduce方法的作用是使用指定的计算逻辑,将多个元素逐个计算处理,最终得到一个结果。简单来说,reduce的过程就是将多个元素转换为一个最终结果。典型的包括将多个数字累加得到一个和,或者累乘得到一个积,或者将多个元素汇总起来得到一个ArrayList。

7. Stream并行编程的底层实现用了什么多线程技术?

使用了 ForkJoinPool 技术。ForkJoinPool是Java 7引入的用于并行执行的任务框架,核心思想是将一个大任务拆分成多个小任务(即fork),然后再将多个小任务的处理结果汇总到一个结果上(即join)。此外,它也提供基本的线程池功能,譬如设置最大并发线程数,关闭线程池等。

8. 能说说 Stream 并行编程的优点和局限性吗?

一般来说,在web应用中不推荐使用 Stream 的并行编程接口,因为 Stream 并行编程的底层是基于 ForkJoinPool ,而 ForkJoinPool 的工作线程数是在虚拟机启动时指定的,如果 Stream 并行执行的任务数量过多或耗时过多,甚至会影响应用程序中其它使用 ForkJoinPool 的功能。

但如果是在某些任务单一、能确保不影响其它任务的场景中,使用 Stream 并行编程能带来编码上的便利性:即使数据源不是线程安全的,通过 Stream 并行编程,也能轻松写出多线程并行处理任务的代码,不需要考虑加锁。

9. ConcurrentHashMap中,有哪些方法具备原子性?

有4个方法具备原子性:

  • compute
  • computeIfAbsent
  • computeIfPresent
  • putIfAbsent

原子性的含义是说:从“判断 ConcurrentHashMap 是否存在指定的key”开始,直到“向 ConcurrentHashMap 写入value”,这是一个原子性的过程 —— 就像加了锁一样,整个过程不会被别的线程打断。

10. 为什么在lambda表达式中引用外部变量时,要求外部变量是final的?怎么绕开这个限制?

在lambda表达式中引用外部变量,会形成一个闭包,在多线程环境下,容易导致线程安全问题,防不胜防。因此,Java规定了,在lambda表达式内部引用外部变量的话,必须是final的,即不可变对象,只能赋值一次,不可修改。

但是,我们可以通过将该外部变量声明为一个数组或一个类(包括容器类)就可以修改其中的值。

更多交流讨论,可关注公众号:员说

附实操代码,提升简历丰富度:Java中的函数式编程icon-default.png?t=L9C2https://gitee.com/cnmemset/javafp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值