Fail-Fast vs Fail-Safe / hashCode & equals / finalize / Exception变化 / System.gc


面试复盘:Java核心与Servlet相关知识点总结

最近参加了一次技术面试,涉及Java SE核心知识和Servlet相关内容。以下是我对面试问题的复盘与总结,希望对大家有所帮助。

1. Fail-Fast和Fail-Safe的区别

在Java集合框架中,fail-fastfail-safe是两种不同的迭代器行为:

  • Fail-Fast(快速失败) :如果在迭代过程中,集合的结构被修改(比如增删元素),迭代器会立即抛出ConcurrentModificationException。这是为了快速暴露问题,避免不可预期的行为。典型例子是ArrayListHashMap的迭代器。
  • Fail-Safe(安全失败) :这种机制允许在迭代时对集合进行修改,通常通过在迭代时操作集合的副本来实现,因此不会抛出异常。CopyOnWriteArrayListConcurrentHashMap是典型代表,但这种方式会牺牲性能和内存。

区别fail-fast追求性能,适合单线程或明确无并发修改的场景;fail-safe更适合并发环境,但开销较大。


2. hashCode和equals方法的重要性体现在哪里

hashCodeequals方法是Object类的核心方法,主要在集合框架(如HashMapHashSet)中发挥作用:

  • equals:用于判断两个对象是否逻辑相等,基于业务需求自定义。
  • hashCode:返回对象的哈希码,用于快速定位对象在哈希表中的位置。

重要性体现在

  1. 一致性 :若a.equals(b)为真,则a.hashCode()必须等于b.hashCode(),否则在HashMap中可能找不到已存的对象。
  2. 性能hashCode提供高效的索引能力,减少equals的调用次数。
  3. 唯一性 :重写时需确保不同对象的hashCode尽量不冲突,避免哈希表退化为链表。

使用场景 :自定义类作为HashMap的key时,必须同时重写这两个方法。


3. finalize()方法何时被调用?finalization的目的是什么?

  • finalize()调用时机finalize()Object类的一个方法,当对象被垃圾回收器(GC)确定为不可达时,GC会在回收前调用它。但调用时机不确定,甚至可能不被调用(例如GC未运行)。
  • finalization的目的 :为对象提供"最后一次自救"机会,比如释放非JVM管理的资源(如文件句柄)。不过,由于其不可靠性,Java 9已标记为@Deprecated,推荐使用try-with-resourcesCleaner

注意 :不要依赖finalize()执行关键逻辑。


4. Java异常处理完成后Exception对象会有什么变化?

在Java中,异常处理(try-catch)完成后,Exception对象本身不会发生变化。它只是一个普通的Java对象,包含异常信息(如堆栈跟踪)。处理完成后:

  • 如果没有引用指向它,会被GC回收。
  • 如果被捕获后存储到变量中(比如catch(Exception e)中的e),则继续存在,直到超出作用域。

关键点 :异常处理不会修改Exception对象的状态,它的状态在抛出时就已经确定。


5. System.gc()和Runtime.gc()的区别

两者都与垃圾回收相关,但有细微差异:

  • System.gc() :静态方法,直接调用Runtime.getRuntime().gc(),是更高层次的封装,建议JVM执行垃圾回收。
  • Runtime.gc()Runtime类的实例方法,更底层,直接触发GC请求。

共同点 :两者都只是"建议"JVM进行GC,不保证立即执行。 区别System.gc()更常用,代码简洁;Runtime.gc()需要获取Runtime实例,稍微繁琐。


6. Marshalling和Demarshalling的区别

  • Marshalling(序列化) :将对象转换为字节流的过程,通常用于数据传输或存储(如Java的ObjectOutputStream)。
  • Demarshalling(反序列化) :将字节流还原为对象的过程(如ObjectInputStream)。

区别:方向相反,Marshalling是"打包",Demarshalling是"解包"。在网络通信(如RMI、JSON)中,这对过程非常常见。


7. 简述什么是Servlet

Servlet 是Java提供的一种服务器端技术,用于处理客户端请求并生成动态响应。它运行在Servlet容器(如Tomcat)中,基于Java语言实现,遵循Servlet API规范。Servlet本质上是一个Java类,通过service()方法处理HTTP请求,常用于Web开发。


8. Servlet的体系结构:过滤器、拦截器及Spring集成

Servlet体系结构由以下组件构成:

  1. Servlet:核心组件,处理请求和响应。
  2. 过滤器(Filter):在请求到达Servlet前或响应返回客户端前进行预处理/后处理(如日志记录、权限校验)。多个过滤器组成过滤链,按配置顺序执行。
  3. 拦截器(Interceptor):Spring特有,作用于MVC框架内,用于拦截Controller方法调用,比Filter更贴近业务逻辑。

Spring集成

  • 在Spring Boot中,Servlet通过@ServletComponentScan注册,或使用ServletRegistrationBean配置。
  • Filter通过@WebFilterFilterRegistrationBean集成。
  • 拦截器通过实现HandlerInterceptor并在WebMvcConfigurer中注册。

区别:Filter是Servlet规范的一部分,作用范围广;拦截器是Spring的扩展,粒度更细。


9. GenericServlet和HttpServlet的区别

  • GenericServlet :一个抽象类,实现了Servlet接口,提供通用实现(如init()destroy()),不绑定特定协议。
  • HttpServlet :继承自GenericServlet,专为HTTP协议设计,增加了doGet()doPost()等方法,处理HTTP请求。

区别GenericServlet更通用,可扩展到非HTTP场景;HttpServlet专注于Web开发,是实际开发中的常用选择。


10. Servlet的生命周期

Servlet生命周期包括以下阶段:

  1. 加载:容器加载Servlet类(通常在首次请求或启动时)。
  2. 实例化:创建Servlet实例。
  3. 初始化 :调用init()方法,执行一次,用于资源准备。
  4. 服务 :每次请求调用service()方法,处理客户端请求。
  5. 销毁 :容器关闭或Servlet移除时,调用destroy()方法,释放资源。

特点:Servlet是单例的,线程不安全,需注意并发问题。


总结

这次面试让我深刻认识到Java基础和Servlet的重要性。从集合的并发处理到异常管理,再到Web开发的Servlet体系,每个知识点都环环相扣。希望这篇复盘能帮助大家梳理知识,也欢迎交流指正!

相关推荐
天天摸鱼的java工程师33 分钟前
蚂蚁金服面试官:你能从JVM源码解释STW吗?
java·后端·面试
liangdabiao34 分钟前
包学会!WooCommerce开源电商的基础架构 - 简要介绍它的核心对象 - 有用有料
后端·架构
未来影子34 分钟前
MCP的SSE重连机制,源码解析
人工智能·后端
bobz9651 小时前
kubevirt 替换为 hostnetwork 的优势
后端
大象席地抽烟1 小时前
Nginx Ingress 证书
后端
心之语歌1 小时前
Java 设计 MCP SSE 配置
java·后端
华仔啊1 小时前
推荐一款比Cursor更懂中国程序员的AI编程工具
前端·后端
海风极客1 小时前
Ping命令这种事情用Go也能优雅实现
后端·go·github
天天摸鱼的java工程师2 小时前
“你能从字节码层面解释JVM内存模型吗?”——面试官的死亡提问
java·后端·面试
这里有鱼汤2 小时前
分享一个年化96%的小市值策略
后端