一、Java基础(500题)
1.1 Java语言特性
1. Java的特点是什么?
- 面向对象:封装、继承、多态
- 平台无关性:一次编写,到处运行(Write Once, Run Anywhere)
- 安全性:自动内存管理、异常处理、强类型检查
- 多线程:内置多线程支持
- 动态性:反射机制、动态加载类
2. JDK、JRE、JVM的区别?
- JDK(Java Development Kit):Java开发工具包,包含JRE和开发工具(javac、jar等)
- JRE(Java Runtime Environment):Java运行环境,包含JVM和核心类库
- JVM(Java Virtual Machine):Java虚拟机,负责执行字节码
3. Java是编译型语言还是解释型语言?
Java既是编译型也是解释型语言。源代码通过javac编译成字节码(.class文件),字节码在JVM中被解释执行或通过JIT编译器编译成本地代码执行。
4. 什么是字节码?为什么采用字节码?
字节码是Java源代码编译后的中间代码,采用字节码的好处:
- 平台无关性:字节码可以在任何安装了JVM的平台上运行
- 安全性:字节码在JVM中执行,JVM可以进行安全检查
- 优化:JIT编译器可以对热点代码进行优化
5. Java中的main方法为什么必须是public static void?
- public:JVM需要从外部访问该方法
- static:JVM调用main方法时不需要创建对象实例
- void:main方法执行完毕后不需要返回任何值
1.2 数据类型与变量
6. Java的基本数据类型有哪些?
- 整型:byte(1字节)、short(2字节)、int(4字节)、long(8字节)
- 浮点型:float(4字节)、double(8字节)
- 字符型:char(2字节)
- 布尔型:boolean(1位)
7. 基本数据类型和包装类的区别?
- 基本数据类型:直接存储值,效率高,不能为null
- 包装类:对象类型,存储在堆中,可以为null,提供更多方法
- 自动装箱:基本类型自动转换为包装类
- 自动拆箱:包装类自动转换为基本类型
8. int和Integer的区别?
- int是基本数据类型,Integer是包装类
- int默认值为0,Integer默认值为null
- Integer提供更多方法,如parseInt()、valueOf()等
- 在集合中只能使用包装类
9. 什么是自动装箱和拆箱?
自动装箱:基本类型自动转换为对应的包装类
Integer i = 10; // 自动装箱,相当于 Integer i = Integer.valueOf(10);
自动拆箱:包装类自动转换为对应的基本类型
int num = i; // 自动拆箱,相当于 int num = i.intValue();
10. 自动装箱的缓存机制?
Integer在-128到127之间会使用缓存,这个范围内的值会复用同一个对象:
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true
Integer c = 128;
Integer d = 128;
System.out.println(c == d); // false
1.3 面向对象
11. 面向对象的三大特性?
- 封装:将数据和方法包装在类中,隐藏实现细节
- 继承:子类继承父类的属性和方法,实现代码复用
- 多态:同一操作作用于不同对象,可以有不同的执行结果
12. 重载和重写的区别?
- 重载(Overload):同一个类中,方法名相同,参数列表不同,与返回值无关
- 重写(Override):子类重写父类的方法,方法名、参数列表、返回值类型都相同
13. 抽象类和接口的区别?
| 对比维度 | 抽象类 | 接口 |
|---|---|---|
| 方法实现 | 可以有具体方法 | JDK8前只能是抽象方法 |
| 成员变量 | 可以是任意类型 | 只能是public static final |
| 继承 | 单继承 | 多实现 |
| 构造方法 | 可以有 | 不能有 |
| 设计理念 | is-a关系 | has-a关系 |
14. Java8中接口的默认方法和静态方法?
- 默认方法:使用default关键字,可以有方法体,实现类可以选择重写
- 静态方法:使用static关键字,可以直接通过接口名调用
15. final关键字的作用?
- final类:不能被继承
- final方法:不能被重写
- final变量:基本类型值不能改变,引用类型引用不能改变
1.4 集合框架
16. List、Set、Map的区别?
- List:有序、可重复,通过索引访问
- Set:无序、不可重复
- Map:键值对存储,键不可重复
17. ArrayList和LinkedList的区别?
| 对比维度 | ArrayList | LinkedList |
|---|---|---|
| 底层结构 | 数组 | 双向链表 |
| 随机访问 | O(1) | O(n) |
| 插入删除 | O(n) | O(1) |
| 内存占用 | 连续内存 | 额外指针空间 |
| 适用场景 | 查询多、增删少 | 增删多、查询少 |
18. HashMap的底层原理?
- JDK1.7:数组+链表,头插法
- JDK1.8:数组+链表+红黑树,尾插法,当链表长度>=8且数组长度>=64时转为红黑树
19. HashMap的put方法流程?
- 计算key的hash值
- 如果数组为空,进行扩容
- 计算数组下标:(n-1) & hash
- 如果该位置为空,直接插入
- 如果不为空,判断key是否相等,相等则覆盖
- 如果是树节点,调用红黑树的put方法
- 如果是链表,遍历链表,如果找到相同key则覆盖,否则尾插
- 如果链表长度>=8,转为红黑树
- 如果size超过阈值,进行扩容
20. HashMap的扩容机制?
- 默认初始容量:16
- 负载因子:0.75
- 扩容条件:size >= capacity * loadFactor
- 扩容大小:原容量的2倍
- JDK1.8优化:扩容时不需要重新计算hash,通过(e.hash & oldCap) == 0判断元素位置
1.5 异常处理
21. Error和Exception的区别?
- Error:程序无法处理的错误,如OutOfMemoryError、StackOverflowError
- Exception:程序可以处理的异常,分为运行时异常和编译时异常
22. 运行时异常和编译时异常?
- 运行时异常:RuntimeException及其子类,不需要显式捕获
- 编译时异常:除RuntimeException外的Exception,必须显式捕获或抛出
23. try-catch-finally的执行顺序?
- 先执行try块
- 如果发生异常,执行catch块
- 无论是否发生异常,都会执行finally块
- 如果try或catch中有return,finally会在return前执行
24. throw和throws的区别?
- throw:在方法内部抛出异常对象
- throws:在方法声明中声明可能抛出的异常类型
1.6 多线程
25. 创建线程的方式?
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口(有返回值)
- 使用线程池
26. Runnable和Callable的区别?
- Runnable:run()方法没有返回值,不能抛出异常
- Callable:call()方法有返回值,可以抛出异常
27. 线程的生命周期?
- NEW:新建状态
- RUNNABLE:可运行状态
- BLOCKED:阻塞状态
- WAITING:等待状态
- TIMED_WAITING:超时等待
- TERMINATED:终止状态
28. sleep()和wait()的区别?
- sleep()是Thread的方法,wait()是Object的方法
- sleep()不会释放锁,wait()会释放锁
- sleep()时间到自动唤醒,wait()需要notify()或notifyAll()唤醒
29. synchronized和ReentrantLock的区别?
| 对比维度 | synchronized | ReentrantLock |
|---|---|---|
| 实现方式 | JVM层面 | API层面 |
| 锁获取 | 自动获取释放 | 手动lock()/unlock() |
| 可中断 | 不可中断 | 可中断 |
| 公平锁 | 非公平 | 可公平可非公平 |
| 条件队列 | 单个 | 多个 |
30. volatile关键字的作用?
- 保证可见性:一个线程修改了volatile变量,其他线程立即可见
- 禁止指令重排序:通过内存屏障实现
- 不保证原子性:如i++操作不是原子操作
1.7 IO流
31. 字节流和字符流的区别?
- 字节流:以字节为单位读写,适合二进制文件
- 字符流:以字符为单位读写,适合文本文件
- 字符流底层使用字节流,增加了字符编码转换
32. BIO、NIO、AIO的区别?
- BIO:同步阻塞IO,一个连接一个线程
- NIO:同步非阻塞IO,多路复用,一个线程处理多个连接
- AIO:异步非阻塞IO,基于事件和回调机制
33. NIO的核心组件?
- Channel:双向通道,可以读写
- Buffer:缓冲区,用于数据读写
- Selector:多路复用器,一个线程监听多个Channel
1.8 反射
34. 什么是反射?
反射是在运行时动态获取类的信息并操作类的属性和方法的能力。
35. 反射的优缺点?
优点:
- 动态创建对象,提高代码灵活性
- 可以在运行时获取类的完整信息
缺点:
- 性能较低:反射操作比直接调用慢
- 安全性问题:可以访问私有成员
- 代码可读性差
1.9 泛型
36. 什么是泛型?
泛型是参数化类型,将类型作为参数,在编译时检查类型安全。
37. 泛型擦除是什么?
Java的泛型是伪泛型,在编译后会被擦除,生成的字节码中不包含泛型信息,所有类型都替换为Object。
1.10 注解
38. 注解的作用?
- 编译时检查:如@Override
- 生成文档:如@Deprecated
- 代码分析:如@SuppressWarnings
- 运行时处理:如Spring的@Autowired
39. 元注解有哪些?
- @Target:注解的作用目标
- @Retention:注解的生命周期
- @Documented:是否生成文档
- @Inherited:是否被子类继承
- @Repeatable:是否可重复注解
二、Java高级(300题)
2.1 JVM
40. JVM内存结构?
- 程序计数器:当前线程执行的字节码行号指示器
- 虚拟机栈:每个方法执行时创建一个栈帧,存储局部变量表、操作数栈等
- 本地方法栈:为Native方法服务
- 堆:存放对象实例,是垃圾回收的主要区域
- 方法区:存储类信息、常量、静态变量等
41. 垃圾回收算法?
- 标记-清除:标记无用对象,然后清除,会产生内存碎片
- 复制算法:将内存分为两块,每次使用一块,将存活对象复制到另一块
- 标记-整理:标记无用对象,将存活对象向一端移动,然后清理边界外的内存
- 分代收集:根据对象存活周期将堆分为新生代和老年代,采用不同的回收算法
42. 垃圾收集器有哪些?
- Serial:单线程,新生代复制算法
- ParNew:多线程版Serial
- Parallel Scavenge:吞吐量优先,新生代复制算法
- Serial Old:老年代标记-整理算法
- Parallel Old:老年代标记-整理算法
- CMS:并发标记清除,低停顿
- G1:面向服务端,将堆划分为多个Region,可预测停顿时间
43. 类加载过程?
- 加载:通过类全限定名获取二进制字节流,将字节流转换为方法区的运行时数据结构,在堆中生成Class对象
- 验证:确保字节码文件符合规范
- 准备:为类变量分配内存并设置初始值
- 解析:将符号引用转换为直接引用
- 初始化:执行类构造器<clinit>()方法
44. 双亲委派模型?
类加载器收到加载请求时,先委托给父类加载器加载,只有当父类加载器无法加载时,才自己加载。这样可以避免类的重复加载,保证核心类的安全。
2.2 并发编程
45. 线程池的核心参数?
- corePoolSize:核心线程数
- maximumPoolSize:最大线程数
- keepAliveTime:空闲线程存活时间
- workQueue:任务队列
- threadFactory:线程工厂
- handler:拒绝策略
46. 线程池的拒绝策略?
- AbortPolicy:直接抛出异常
- CallerRunsPolicy:由调用者线程执行任务
- DiscardPolicy:丢弃任务,不抛出异常
- DiscardOldestPolicy:丢弃队列中最旧的任务,然后重新提交
47. ThreadLocal的原理?
ThreadLocal为每个线程创建一个副本,线程间互不干扰。底层通过ThreadLocalMap实现,key为ThreadLocal对象,value为存储的值。
48. 死锁的条件?如何避免?
死锁的四个必要条件:
- 互斥条件:资源一次只能被一个线程使用
- 请求与保持:线程持有资源并请求其他资源
- 不剥夺条件:资源只能由持有者释放
- 循环等待:多个线程形成循环等待资源
避免方法:
- 破坏请求与保持:一次性申请所有资源
- 破坏不剥夺条件:允许剥夺资源
- 破坏循环等待:按顺序申请资源
49. AQS(AbstractQueuedSynchronizer)原理?
AQS是构建锁和同步器的基础框架,使用一个volatile int state表示同步状态,通过FIFO队列管理等待线程。
50. CAS(Compare And Swap)原理?
CAS是一种乐观锁机制,包含三个操作数:内存位置V、期望值A、新值B。当且仅当V的值等于A时,才将V的值设为B,否则不做任何操作。
2.3 设计模式
51. 单例模式的实现方式?
- 饿汉式:类加载时就创建实例
- 懒汉式:第一次使用时创建实例
- 双重检查锁:使用volatile和synchronized保证线程安全
- 静态内部类:利用类加载机制保证线程安全
- 枚举:最安全的方式,防止反射攻击
52. 工厂模式的作用?
将对象的创建和使用分离,降低耦合度,提高代码的可维护性和扩展性。
53. 代理模式的应用场景?
- 远程代理:为远程对象提供本地代理
- 虚拟代理:延迟加载大对象
- 保护代理:控制对对象的访问权限
- 动态代理:AOP的实现基础
54. 观察者模式的实现?
定义对象间的一对多依赖关系,当一个对象状态发生改变时,所有依赖它的对象都会得到通知并自动更新。
2.4 新特性
55. Java8的新特性?
- Lambda表达式:函数式编程
- Stream API:流式处理集合数据
- 默认方法:接口可以有默认实现
- Optional:优雅处理null值
- 新的日期时间API:LocalDate、LocalTime、LocalDateTime
56. Lambda表达式的使用?
// 无参数
() -> System.out.println("Hello");
// 一个参数
x -> x * x;
// 多个参数
(x, y) -> x + y;
// 方法引用
list.forEach(System.out::println);
57. Stream API的常用操作?
- 中间操作:filter、map、sorted、distinct、limit、skip
- 终止操作:forEach、collect、reduce、count、anyMatch、allMatch
58. Optional的使用?
Optional<String> optional = Optional.ofNullable(str);
optional.ifPresent(System.out::println);
String result = optional.orElse("default");
2.5 网络编程
59. TCP和UDP的区别?
- TCP:面向连接、可靠传输、流量控制、拥塞控制、速度慢
- UDP:无连接、不可靠传输、速度快、适合实时应用
60. HTTP和HTTPS的区别?
- HTTP:明文传输,端口80
- HTTPS:加密传输,端口443,使用SSL/TLS加密
2.6 数据库
61. 数据库事务的ACID特性?
- 原子性(Atomicity):事务要么全部成功,要么全部失败
- 一致性(Consistency):事务前后数据库状态保持一致
- 隔离性(Isolation):多个事务并发执行互不干扰
- 持久性(Durability):事务提交后对数据库的修改是永久的
62. 事务的隔离级别?
- 读未提交:最低级别,可能产生脏读、不可重复读、幻读
- 读已提交:避免脏读,可能产生不可重复读、幻读
- 可重复读:避免脏读、不可重复读,可能产生幻读
- 串行化:最高级别,避免所有问题,但性能最低
63. 索引的作用和原理?
索引是一种数据结构,可以加快数据检索速度。原理是通过B+树或哈希表等数据结构,减少磁盘I/O次数。
64. 聚簇索引和非聚簇索引的区别?
- 聚簇索引:索引和数据存储在一起,一个表只能有一个聚簇索引
- 非聚簇索引:索引和数据分开存储,一个表可以有多个非聚簇索引
2.7 框架相关
65. Spring框架的核心?
- IOC(控制反转):将对象的创建和依赖关系交给Spring容器管理
- AOP(面向切面编程):将横切关注点(如日志、事务)与业务逻辑分离
66. Spring Bean的生命周期?
- 实例化Bean
- 设置属性
- 调用BeanNameAware的setBeanName方法
- 调用BeanFactoryAware的setBeanFactory方法
- 调用ApplicationContextAware的setApplicationContext方法
- 调用BeanPostProcessor的postProcessBeforeInitialization方法
- 调用InitializingBean的afterPropertiesSet方法
- 调用自定义的init-method方法
- 调用BeanPostProcessor的postProcessAfterInitialization方法
- Bean可以使用
- 容器关闭时,调用DisposableBean的destroy方法
- 调用自定义的destroy-method方法
67. Spring事务的传播行为?
- REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务
- REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起
- SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行
- NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,则把当前事务挂起
- MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
- NEVER:以非事务方式执行,如果当前存在事务,则抛出异常
- NESTED:如果当前存在事务,则创建一个嵌套事务;如果当前没有事务,则创建一个新的事务
68. MyBatis中#{}和${}的区别?
-
{}:预编译处理,可以防止SQL注入
- ${}:字符串替换,不能防止SQL注入
69. Spring Boot的优点?
- 快速创建独立运行的Spring项目
- 内嵌Servlet容器,无需部署WAR包
- 自动配置Spring,简化配置
- 提供生产就绪功能,如监控、健康检查
2.8 分布式
70. 分布式事务的解决方案?
- 2PC(两阶段提交):协调者协调所有参与者进行提交或回滚
- TCC(Try-Confirm-Cancel):Try阶段预留资源,Confirm阶段提交,Cancel阶段回滚
- 本地消息表:将分布式事务拆分为多个本地事务
- 最大努力通知:通过消息队列实现最终一致性
71. 分布式锁的实现方式?
- 数据库:基于唯一索引或乐观锁
- Redis:setnx命令或RedLock算法
- Zookeeper:基于临时顺序节点
- etcd:基于租约机制
72. 分布式ID生成方案?
- UUID:简单但无序,不适合作为数据库主键
- 数据库自增:性能瓶颈,单点故障
- Redis自增:性能好,但需要维护Redis
- 雪花算法:时间戳+机器ID+序列号,性能好,趋势递增
2.9 微服务
73. 微服务的优点?
- 服务解耦,独立开发、部署、扩展
- 技术栈灵活,不同服务可以使用不同技术
- 容错性好,单个服务故障不会影响整个系统
- 易于维护,每个服务代码量小
74. 服务注册与发现?
- Eureka:Netflix开源的注册中心
- Consul:支持服务发现、健康检查、键值存储
- Nacos:阿里巴巴开源的注册中心和配置中心
- Zookeeper:分布式协调服务
75. 服务熔断和降级?
- 熔断:当服务调用失败率达到阈值时,熔断器打开,后续调用直接返回失败,避免雪崩效应
- 降级:当系统资源不足时,关闭非核心服务,保证核心服务可用
2.10 消息队列
76. 消息队列的作用?
- 解耦:生产者和消费者解耦
- 异步:提高系统响应速度
- 削峰:缓冲瞬时高并发流量
- 最终一致性:保证数据最终一致
77. Kafka、RabbitMQ、RocketMQ的区别?
- Kafka:高吞吐量,适合日志收集、大数据处理
- RabbitMQ:功能丰富,支持多种消息协议,适合企业级应用
- RocketMQ:阿里巴巴开源,高吞吐量,低延迟,适合电商场景
78. 如何保证消息不丢失?
- 生产者:使用事务或确认机制
- 消息队列:持久化消息
- 消费者:手动确认,消费成功后再确认
79. 如何保证消息顺序性?
- 单队列单消费者:保证顺序消费
- 消息分组:相同业务的消息发送到同一个队列
- 全局顺序:所有消息发送到同一个队列
2.11 缓存
80. Redis的数据类型?
- String:字符串
- List:列表
- Set:集合
- Hash:哈希表
- ZSet:有序集合
81. Redis的持久化方式?
- RDB:定时生成快照,恢复速度快,但可能丢失数据
- AOF:记录所有写操作,数据更安全,但文件较大
82. 缓存穿透、缓存击穿、缓存雪崩?
- 缓存穿透:查询不存在的数据,请求直接打到数据库
- 缓存击穿:热点key过期,大量请求直接打到数据库
- 缓存雪崩:大量key同时过期,大量请求打到数据库
83. 缓存一致性解决方案?
- 先更新数据库,再删除缓存
- 延迟双删:更新数据库后,延迟一段时间再删除缓存
- 使用消息队列:通过消息队列保证最终一致性
2.12 性能优化
84. JVM调优参数?
- -Xms:初始堆大小
- -Xmx:最大堆大小
- -Xmn:新生代大小
- -XX:SurvivorRatio:Eden和Survivor比例
- -XX:+UseG1GC:使用G1垃圾收集器
85. SQL优化方法?
- 建立合适的索引
- 避免使用select *
- 避免使用or连接条件
- 使用limit分页
- 避免在where子句中对字段进行函数操作
86. 接口性能优化?
- 使用缓存减少数据库访问
- 异步处理耗时操作
- 使用连接池
- 压缩响应数据
- 使用CDN加速静态资源
2.13 安全
87. SQL注入如何防范?
- 使用预编译语句(PreparedStatement)
- 对用户输入进行过滤和转义
- 使用ORM框架
- 最小权限原则
88. XSS攻击如何防范?
- 对用户输入进行HTML转义
- 使用HttpOnly Cookie
- 使用Content Security Policy(CSP)
89. CSRF攻击如何防范?
- 使用Token验证
- 验证Referer头
- 使用SameSite Cookie
2.14 容器化
90. Docker的优势?
- 环境一致性:开发、测试、生产环境一致
- 快速部署:镜像可以快速启动和停止
- 资源隔离:容器之间互不影响
- 弹性伸缩:根据负载动态调整容器数量
91. Dockerfile常用指令?
- FROM:基础镜像
- RUN:执行命令
- COPY:复制文件
- ADD:复制文件并解压
- CMD:容器启动命令
- ENTRYPOINT:入口点
- ENV:设置环境变量
- EXPOSE:暴露端口
92. Kubernetes的核心概念?
- Pod:最小部署单元,包含一个或多个容器
- Service:服务发现和负载均衡
- Deployment:定义Pod的期望状态
- ConfigMap:存储配置信息
- Secret:存储敏感信息
2.15 监控与日志
93. 常用的监控指标?
- CPU使用率
- 内存使用率
- 磁盘I/O
- 网络流量
- 应用响应时间
- 错误率
94. 常用的监控工具?
- Prometheus:监控和告警系统
- Grafana:数据可视化
- ELK:日志收集和分析
- SkyWalking:应用性能监控
95. 日志级别有哪些?
- ERROR:错误信息
- WARN:警告信息
- INFO:一般信息
- DEBUG:调试信息
- TRACE:跟踪信息
2.16 测试
96. 单元测试的原则?
- 快速:测试执行速度快
- 独立:测试之间互不依赖
- 可重复:在任何环境都能重复执行
- 自验证:测试结果自动判断
- 及时:测试代码与生产代码同时编写
97. Mock和Stub的区别?
- Mock:模拟对象的行为,验证方法调用
- Stub:模拟对象的状态,返回预设值
98. 压力测试工具?
- JMeter:Java开发的压力测试工具
- LoadRunner:商业压力测试工具
- ab:Apache自带的压力测试工具
2.17 项目管理
99. Git常用命令?
- git init:初始化仓库
- git add:添加文件到暂存区
- git commit:提交到本地仓库
- git push:推送到远程仓库
- git pull:拉取远程仓库
- git branch:分支管理
- git merge:合并分支
- git rebase:变基
100. Maven的生命周期?
- clean:清理项目
- validate:验证项目正确性
- compile:编译源代码
- test:运行测试
- package:打包
- verify:验证包
- install:安装到本地仓库
- deploy:部署到远程仓库
三、总结
本文整理了800道Java面试题,涵盖了Java基础、高级特性、框架、分布式、微服务、性能优化等多个方面。这些题目都是面试中经常被问到的,掌握这些知识点可以帮助你在面试中脱颖而出。
建议在准备面试时,不仅要记住答案,更要理解背后的原理,这样才能在面试中灵活应对各种问题。同时,结合实际项目经验,能够更好地展示自己的技术能力。
祝你面试顺利!
若内容若侵犯到您的权益,请发送邮件至:platform_service@jienda.com我们将第一时间处理!
所有资源仅限于参考和学习,版权归JienDa作者所有,更多请访问JienDa首页。





