2020-11-16 15:07:47
海康威视研发一面核心问题及解答要点如下:
技术基础问题Java八种基本类型及int取值范围
八种基本类型:byte、short、int、long、float、double、char、boolean。
int为32位有符号整数,取值范围:-231(-2,147,483,648)到 231-1(2,147,483,647)。
封装类(如Integer)与基本类型的区别
缓存机制:Integer在[-128,127]区间内使用IntegerCache.cache[]静态缓存,直接通过==比较可能为true(因引用相同);超出此范围则通过new Integer(x)创建新对象,需用equals()比较值。
自动装箱/拆箱:如Integer a = 10;(装箱)和int b = a;(拆箱)由编译器自动处理,但需注意空指针风险(如Integer c = null; int d = c;会抛NullPointerException)。
Lambda表达式(JDK 1.8+)
Lambda是函数式编程的核心,用于简化匿名内部类。语法:(参数) -> { 表达式或语句 }。
Python与Java差异:Python的Lambda更灵活(可含多语句),但Java的Lambda需匹配函数式接口(如Runnable、Comparator),且通常为单表达式(可省略return和花括号)。
HashMap与ConcurrentHashMap源码级问题
HashMap:基于数组+链表/红黑树实现,put(key, value)时若键已存在,会覆盖原值并返回旧值,不会报异常。
ConcurrentHashMap:通过分段锁(JDK 1.7)或CAS+synchronized(JDK 1.8)实现并发,put操作在键存在时同样覆盖值。
线程安全机制:ConcurrentHashMap通过减少锁粒度(如JDK 1.8的桶级锁)提升并发性能,而非完全避免竞争。
线程池原理与异常处理
核心组件:
工作队列:存储待执行任务(如LinkedBlockingQueue)。
拒绝策略:队列满时触发(如AbortPolicy抛异常、CallerRunsPolicy由调用线程执行)。
断电恢复:
内存数据丢失后,需依赖持久化机制(如Redis的AOF日志记录任务队列,或消息队列框架如RabbitMQ的持久化队列)。
分布式队列(如Kafka)通过多副本和日志同步保证数据可靠性。
数据库事务日志与删除操作
三种日志类型:
Undo Log:记录事务修改前的数据,用于回滚和MVCC(多版本并发控制)。
Redo Log:记录事务修改后的数据,用于崩溃恢复(保证已提交事务的持久性)。
Binlog:MySQL Server层日志,用于主从复制和数据恢复。
DELETE操作:仅标记记录为删除(通过Undo Log回滚),实际数据由后台线程清理(如InnoDB的purge操作)。
复合索引最左匹配原则
原理:B+树索引按字段顺序存储,查询需从左到右依次匹配(如索引(A,B,C)可优化A=1、A=1 AND B=2,但无法优化B=2)。
源码层面:InnoDB通过比较索引字段的顺序和查询条件,决定是否使用索引(若全表扫描更快则放弃索引)。
自增ID耗尽问题
原因:自增ID(如INT UNSIGNED最大42亿)因删除操作不会复用,频繁增删会导致ID耗尽。
解决方案:
改用BIGINT(最大18位数字)。
使用UUID或雪花算法(Snowflake)生成分布式ID。
回收已删除ID(需业务支持,如软删除+定期清理)。
LIKE语句与索引使用
索引失效场景:
左模糊查询(如%abc或%abc%)。
查询字段为长文本(如TEXT类型)且未使用前缀索引。
优化建议:
避免左模糊,改用全文索引(如FULLTEXT)或倒排索引。
对长文本字段使用前缀索引(如INDEX(column(10)))。
知识获取方式
面试官强调系统学习优于临时刷面经,建议通过:
官方文档(如Oracle Java文档、MySQL源码分析)。
经典书籍(如《Java并发编程实战》《高性能MySQL》)。
开源项目(如阅读HashMap、ConcurrentHashMap源码)。
项目经验不足的应对
重点描述项目中的技术难点与解决思路(如性能优化、并发控制),而非堆砌项目数量。
示例:若项目涉及高并发,可结合线程池、锁机制或分布式队列展开说明。
并发编程(如Java内存模型、锁优化)。
分布式系统(如消息队列、分布式事务)。
数据库底层原理(如索引结构、事务隔离级别)。