【31-40期】从Java反射到SSO:深度解析面试高频问题
🚀 作者 :“码上有前”
🚀 文章简介 :Java
🚀 欢迎小伙伴们 点赞👍、收藏⭐、留言💬
文章题目:从Java反射到SSO:深度解析31-40期面试高频问题
摘要:
本文针对Java开发中31-40期面试问题,从性能优化、缓存策略、加密查询到分布式锁和并发控制,全面解析高频技术问题。通过理论结合代码实例的方式,阐述每个问题的原理、应用场景及最佳实践,帮助开发者快速掌握这些重要知识点,为高难度面试和实际开发提供强有力的参考。
1. Java反射和new效率对比,差距有多大?
回答:
反射效率较new
低,因为反射需要动态解析类的元信息,绕过JVM的直接优化路径。
原理与逻辑:
new
是直接操作字节码;- 反射通过
Method.invoke()
调用方法,多了一层开销。
最佳实践:
反射适用于框架底层开发,不适合高频调用。
Constructor<MyClass> constructor = MyClass.class.getConstructor();
MyClass instance = constructor.newInstance(); // 慢于 new MyClass()
2. 谈谈过滤器和拦截器的区别?
回答:
- 过滤器(Filter):基于Servlet规范,作用于请求和响应;
- 拦截器(Interceptor):基于Spring AOP,作用于Controller方法执行前后。
最佳实践:
过滤器用作请求预处理:
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
System.out.println("过滤器执行");
chain.doFilter(req, res);
}
}
拦截器用于权限校验:
public class MyInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("拦截器执行");
return true;
}
}
3. Redis中有哪些阻塞问题以及如何解决?
回答:
Redis阻塞问题通常由慢查询或命令如BLPOP
导致。
解决方案:
- 设置慢查询日志;
- 使用分片或集群化;
- 避免过大数据结构的操作(如大集合的
LRANGE
)。
最佳实践:
优化查询:
CONFIG SET slowlog-log-slower-than 10000
4. 如何对加密后的数据进行模糊查询?
回答:
加密后的数据无法直接模糊查询,但可以使用以下方法:
- 加密前索引;
- 使用Homomorphic Encryption(同态加密)。
最佳实践:
对数据的摘要字段创建索引。
String hashedValue = hash("sensitive_data");
5. 电商库存扣减如何设计?如何防止超卖?
回答:
- 防止超卖:使用分布式锁或乐观锁控制并发更新;
- 设计方案:库存数据缓存+数据库校验。
最佳实践:
使用Redis实现分布式锁:
String lockKey = "product_123_lock";
if (redis.setIfAbsent(lockKey, "1", 5, TimeUnit.SECONDS)) {
// 更新库存
redis.delete(lockKey);
}
6. MySQL分表后,如何做分页查询?
回答:
- 使用分库分表中间件(如ShardingSphere);
- 分表后先分页查询某一分表,再汇总结果。
最佳实践:
结合逻辑表字段查询:
SELECT * FROM orders_2023_01 WHERE id > ? LIMIT 10;
7. select……for update会锁表还是锁行?
回答:
- 锁行:加索引的情况下,
for update
会锁定匹配的行; - 锁表:没有索引时会锁表。
最佳实践:
确保索引存在:
SELECT * FROM orders WHERE id = 1 FOR UPDATE;
8. ReadWriteLock读写之间是互斥的吗?
回答:
- 读锁共享:多个线程可以同时读取;
- 写锁独占:写操作会阻塞读操作和其他写操作。
最佳实践:
使用ReentrantReadWriteLock
:
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
try {
// 读操作
} finally {
lock.readLock().unlock();
}
9. 线程池中多余的线程是如何回收的?
回答:
线程池通过keepAliveTime
回收闲置线程。
原理与逻辑:
线程超过keepAliveTime
未被使用时,会被销毁。
最佳实践:
配置线程池:
new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
10. SSO单点登录和OAuth2.0的区别?
回答:
- SSO:在多个系统中共享登录态;
- OAuth2.0:用于第三方授权,允许用户授权其他应用访问其资源。
最佳实践:
SSO实现用户认证:
String token = jwt.sign(payload, secret);
OAuth2.0用于授权:
GET /authorize?response_type=code&client_id=clientId&redirect_uri=callback_url
总结:
本篇文章详细解析了31-40期的面试问题,涵盖反射效率、分布式锁、缓存优化等技术点,通过理论与代码实例的结合,帮助开发者理解这些核心问题的解决方案,在实际开发和面试中应对自如。