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体系,每个知识点都环环相扣。希望这篇复盘能帮助大家梳理知识,也欢迎交流指正!

相关推荐
uhakadotcom1 分钟前
Tableau入门:数据可视化的强大工具
后端·面试·github
demonlg011220 分钟前
Go 语言 fmt 模块的完整方法详解及示例
开发语言·后端·golang
程序员鱼皮28 分钟前
2025 年最全Java面试题 ,热门高频200 题+答案汇总!
java·后端·面试
测试盐30 分钟前
django入门教程之cookie和session【六】
后端·python·django
天草二十六_简村人1 小时前
Rabbitmq消息被消费时抛异常,进入Unacked 状态,进而导致消费者不断尝试消费(下)
java·spring boot·分布式·后端·rabbitmq
uhakadotcom1 小时前
APM系统简介及案例
后端·面试·github
易元1 小时前
设计模式-外观模式
后端
低头不见1 小时前
Spring Boot 的启动流程
java·spring boot·后端
uhakadotcom2 小时前
Syslog投递日志到SIEM:基础知识与实践
后端·面试·github
uhakadotcom2 小时前
Flume 和 Logstash:日志收集工具的对比
后端·面试·github