面试复盘:Java核心与Servlet相关知识点总结
最近参加了一次技术面试,涉及Java SE核心知识和Servlet相关内容。以下是我对面试问题的复盘与总结,希望对大家有所帮助。
1. Fail-Fast和Fail-Safe的区别
在Java集合框架中,fail-fast
和fail-safe
是两种不同的迭代器行为:
- Fail-Fast(快速失败) :如果在迭代过程中,集合的结构被修改(比如增删元素),迭代器会立即抛出
ConcurrentModificationException
。这是为了快速暴露问题,避免不可预期的行为。典型例子是ArrayList
和HashMap
的迭代器。 - Fail-Safe(安全失败) :这种机制允许在迭代时对集合进行修改,通常通过在迭代时操作集合的副本来实现,因此不会抛出异常。
CopyOnWriteArrayList
和ConcurrentHashMap
是典型代表,但这种方式会牺牲性能和内存。
区别 :fail-fast
追求性能,适合单线程或明确无并发修改的场景;fail-safe
更适合并发环境,但开销较大。
2. hashCode和equals方法的重要性体现在哪里
hashCode
和equals
方法是Object
类的核心方法,主要在集合框架(如HashMap
、HashSet
)中发挥作用:
equals
:用于判断两个对象是否逻辑相等,基于业务需求自定义。hashCode
:返回对象的哈希码,用于快速定位对象在哈希表中的位置。
重要性体现在:
- 一致性 :若
a.equals(b)
为真,则a.hashCode()
必须等于b.hashCode()
,否则在HashMap
中可能找不到已存的对象。 - 性能 :
hashCode
提供高效的索引能力,减少equals
的调用次数。 - 唯一性 :重写时需确保不同对象的
hashCode
尽量不冲突,避免哈希表退化为链表。
使用场景 :自定义类作为HashMap
的key时,必须同时重写这两个方法。
3. finalize()方法何时被调用?finalization的目的是什么?
finalize()
调用时机 :finalize()
是Object
类的一个方法,当对象被垃圾回收器(GC)确定为不可达时,GC会在回收前调用它。但调用时机不确定,甚至可能不被调用(例如GC未运行)。- finalization的目的 :为对象提供"最后一次自救"机会,比如释放非JVM管理的资源(如文件句柄)。不过,由于其不可靠性,Java 9已标记为
@Deprecated
,推荐使用try-with-resources
或Cleaner
。
注意 :不要依赖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体系结构由以下组件构成:
- Servlet:核心组件,处理请求和响应。
- 过滤器(Filter):在请求到达Servlet前或响应返回客户端前进行预处理/后处理(如日志记录、权限校验)。多个过滤器组成过滤链,按配置顺序执行。
- 拦截器(Interceptor):Spring特有,作用于MVC框架内,用于拦截Controller方法调用,比Filter更贴近业务逻辑。
Spring集成:
- 在Spring Boot中,Servlet通过
@ServletComponentScan
注册,或使用ServletRegistrationBean
配置。 - Filter通过
@WebFilter
或FilterRegistrationBean
集成。 - 拦截器通过实现
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生命周期包括以下阶段:
- 加载:容器加载Servlet类(通常在首次请求或启动时)。
- 实例化:创建Servlet实例。
- 初始化 :调用
init()
方法,执行一次,用于资源准备。 - 服务 :每次请求调用
service()
方法,处理客户端请求。 - 销毁 :容器关闭或Servlet移除时,调用
destroy()
方法,释放资源。
特点:Servlet是单例的,线程不安全,需注意并发问题。
总结
这次面试让我深刻认识到Java基础和Servlet的重要性。从集合的并发处理到异常管理,再到Web开发的Servlet体系,每个知识点都环环相扣。希望这篇复盘能帮助大家梳理知识,也欢迎交流指正!