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; // 对特定模块开放  
}  

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

相关推荐
passionSnail1 分钟前
《用MATLAB玩转游戏开发:从零开始打造你的数字乐园》基础篇(2D图形交互)-《打砖块:向量反射与实时物理模拟》MATLAB教程
开发语言·matlab·交互
Themberfue5 分钟前
RabbitMQ ②-工作模式
开发语言·分布式·后端·rabbitmq
极小狐13 分钟前
如何使用极狐GitLab 软件包仓库功能托管 helm chart?
java·linux·服务器·数据库·c#·gitlab·maven
有梦想的攻城狮25 分钟前
spring中的@Inject注解详情
java·后端·spring·inject
Top`33 分钟前
服务预热原理
java·后端·spring
在下小孙42 分钟前
Lua—元表(Metatable)
开发语言·lua·元表
Yuze_Neko1 小时前
C#异步Task,await,async和Unity同步协程
开发语言·unity·c#
努力的小帅1 小时前
c++——二叉树进阶
开发语言·数据结构·c++·学习·算法·面试
loveLifeLoveCoding1 小时前
springboot 加载 tomcat 源码追踪
java·spring boot·spring
幽络源小助理1 小时前
SpringBoot框架开发网络安全科普系统开发实现
java·spring boot·后端·spring·web安全