Java面试易忽略知识点

1. CompletableFuture中thenApply()thenCompose()的区别

考察点 :组合式异步编程
解析

  • **thenApply()**:接收前序任务结果,返回普通对象(同步转换),适用简单数据处理。
  • **thenCompose()**:接收前序任务结果,返回新的CompletableFuture(异步嵌套),用于链式调用异步任务。
    示例
复制代码

java

复制代码
CompletableFuture.supplyAsync(() -> "Hello")  
    .thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World")); // 链式异步  

2. Java模块化系统(JPMS)如何解决"自动模块"问题?

考察点 :模块化依赖管理
解析

  • 自动模块:非模块化JAR包会被视为自动模块,导出所有包并读取所有其他模块。

  • 解决方案 :在module-info.java中显式声明依赖:

    复制代码

    java

    复制代码
    requires transitive com.example.lib; // 传递依赖  

3. 如何用GraalVM将Spring Boot应用编译为原生镜像?

考察点 :AOT编译与云原生优化
解析

  1. 添加依赖

    复制代码

    xml

    复制代码
    <dependency>  
        <groupId>org.springframework.experimental</groupId>  
        <artifactId>spring-native</artifactId>  
    </dependency>  
  2. 编译命令

    复制代码

    bash

    复制代码
    mvn spring-boot:build-image  

优势:启动时间<50ms,内存占用降低60%。


4. 记录类型(Records)能否实现Builder模式?

考察点 :不可变数据结构设计
解析

  • 限制 :Records默认生成final类,字段不可变,需通过静态内部类模拟Builder:

    复制代码

    java

    复制代码
    public record User(Long id, String name) {  
        public static class Builder {  
            private Long id;  
            private String name;  
            // Setter方法  
            public User build() { return new User(id, name); }  
        }  
    }  

5. 模式匹配在instanceofswitch中的性能差异

考察点 :新特性底层优化
解析

  • **instanceof模式匹配**:编译器生成类型检查代码,性能与传统instanceof+强制转型相当。
  • **switch模式匹配**(Java 21预览):生成跳表优化,适合多分支场景,性能优于链式if-else

6. ZGC的"染色指针"如何实现并发标记?

考察点 :低延迟GC原理
解析

  • 指针元数据:在64位指针中存储标记位、重定位状态等,无需STW即可更新对象状态。
  • 读屏障:在访问对象时动态修正指针,保证并发标记期间线程安全。

7. JFR(Java Flight Recorder)如何定位线程阻塞问题?

考察点 :性能分析工具
步骤

  1. 录制JFR数据:

    复制代码

    bash

    复制代码
    jcmd <pid> JFR.start duration=60s filename=blocking.jfr  
  2. 分析jdk.JavaMonitorWait事件,查看持有锁的线程栈。


8. 如何用JMH测试StringBufferStringBuilder的性能差异?

考察点 :基准测试实践
代码

复制代码

java

复制代码
@BenchmarkMode(Mode.Throughput)  
public class StringBenchmark {  
    @Benchmark  
    public void testStringBuffer() {  
        StringBuffer sb = new StringBuffer();  
        for (int i=0; i<1000; i++) sb.append(i);  
    }  
    // 类似实现StringBuilder测试  
}  

结论 :单线程下StringBuilder快30%,多线程需考虑锁竞争。


9. 密封类(Sealed Classes)在领域驱动设计(DDD)中的应用

考察点 :领域模型限制
场景:定义核心领域对象,限制子类扩展:

复制代码

java

复制代码
public sealed interface PaymentMethod permits CreditCard, PayPal {}  
public final class CreditCard implements PaymentMethod { /* 字段校验逻辑 */ }  

优势:强制业务规则,避免模型污染。


10. 虚拟线程(Project Loom)与传统线程池的资源消耗对比

考察点 :轻量级并发模型
数据

  • 传统线程:1个线程 ≈ 1MB栈内存,万级线程消耗GB级内存。
  • 虚拟线程 :1个虚拟线程 ≈ 1KB内存,支持百万级并发。
    适用场景:IO密集型服务(如API网关、爬虫)。

11. 静态类初始化陷阱:静态代码块与构造函数的执行顺序

考察点 :类加载机制
示例

复制代码

java

复制代码
class Parent {  
    static { System.out.println("Parent静态块"); }  
    Parent() { System.out.println("Parent构造器"); }  
}  
class Child extends Parent {  
    static { System.out.println("Child静态块"); }  
    Child() { System.out.println("Child构造器"); }  
}  
// 输出顺序:Parent静态块 → Child静态块 → Parent构造器 → Child构造器  

12. Optional.orElse()orElseGet()的性能差异

考察点 :延迟计算优化
解析

  • **orElse()**:无论Optional是否为空,都会执行参数表达式。
  • **orElseGet()**:仅在Optional为空时执行Supplier逻辑,适合高开销操作。

13. 方法句柄(MethodHandle)与反射的性能对比

考察点 :底层API优化
数据

  • 反射调用:每次调用检查访问权限,性能较差。
  • 方法句柄 :JVM内联优化,性能接近直接方法调用(快5-10倍)。
    示例
复制代码

java

复制代码
MethodHandles.Lookup lookup = MethodHandles.lookup();  
MethodHandle mh = lookup.findVirtual(String.class, "length", MethodType.methodType(int.class));  
int len = (int) mh.invokeExact("test"); // len=4  

14. JNI调用的内存泄漏风险及解决方案

考察点 :本地方法安全
风险点

  • 未正确释放NewGlobalRef创建的全局引用。
  • 本地代码中直接修改Java对象未同步回JVM。
    解决 :使用try-finally块确保释放资源,或换用JNA/JNR等安全框架。

15. 动态代理在Spring AOP中的性能瓶颈

考察点 :代理机制优化
问题 :JDK动态代理基于接口,CGLIB基于类,后者生成子类可能导致方法final修饰符冲突。
优化 :Spring 5默认使用CGLIB,可通过@EnableAspectJAutoProxy(proxyTargetClass=true)强制使用。


16. 弱引用(WeakReference)在缓存设计中的误用场景

考察点 :引用类型特性
陷阱 :若缓存键通过弱引用持有,可能被GC提前回收,导致缓存失效。
方案 :使用WeakHashMap或搭配ReferenceQueue手动清理。


17. JVM退出时的钩子函数(ShutdownHook)执行限制

考察点 :JVM生命周期
规则

  • 钩子函数必须快速执行,超时会被强制终止。
  • 已执行System.exit()后注册的钩子无效。

18. 常量折叠(Constant Folding)对程序逻辑的潜在影响

考察点 :编译器优化
示例

复制代码

java

复制代码
final int a = 1;  
final int b = 2;  
System.out.println(a + b); // 编译时优化为3,字节码中无加法指令  

注意:依赖编译时常量的计算可能隐藏逻辑错误。


19. 伪共享(False Sharing)在并发计数器的解决方案

考察点 :CPU缓存优化
问题 :多个线程修改同一缓存行的不同变量,导致缓存失效。
解决

复制代码

java

复制代码
@Contended // JVM参数需加-XX:-RestrictContended  
public class Counter {  
    public volatile long value1;  
    public volatile long value2;  
}  

20. Java模块化系统中如何允许第三方库反射访问私有字段?

考察点 :模块权限控制
配置 :在module-info.java中开放包:

复制代码

java

复制代码
open module com.example.app {  
    opens com.example.internal to spring.core; // 对特定模块开放  
}  

风险:过度开放可能导致封装性破坏。

相关推荐
小画家~15 分钟前
第三:go 操作mysql
开发语言·mysql·golang
修炼成精15 分钟前
C#实现的一个简单的软件保护方案
java·开发语言·c#
乌云暮年27 分钟前
算法刷题整理合集(四)
java·开发语言·算法·dfs·bfs
二进制人工智能30 分钟前
【QT 多线程示例】两种多线程实现方式
开发语言·qt
Biomamba生信基地1 小时前
R语言基础小测验
开发语言·r语言·生信
studyer_domi1 小时前
Matlab 汽车电子驻车系统仿真分析
开发语言·matlab·汽车
代码代码快快显灵1 小时前
SpringSecurity——如何获取当前登录用户的信息
java·开发语言·springsecurity
红虾程序员1 小时前
python函数的多种参数使用形式
开发语言·python·pycharm
MetaverseMan1 小时前
Rust Tokio 和 Node.js 异步的相似之处
开发语言·rust·node.js
Luo_LA1 小时前
【排序算法对比】快速排序、归并排序、堆排序
java·算法·排序算法