Java

浏览该分类下的所有文章

如何正确的释放资源?

文章指出在 Java 中手动在 finally 块里关闭 I/O 流会导致代码冗长、易忘记关闭且异常处理不佳,示例代码即有此弊端。推荐使用 Java 7 引入的 try‑with‑resources,前提是资源实现 AutoCloseable,代码更简洁、自动释放且无需关心关闭顺序。文中也给出手动关闭的可变参数工具方法,但提醒其必须严格按顺序调用。综上,最优雅可靠的资源释放方式仍是 try‑with‑resources。

如何实现线程复用?

线程池通过维护 Worker 对象实现复用。execute 先在核心线程数范围内尝试 addWorker 创建线程,若达上限则把任务放入 workQueue。Worker 持有 Thread 并实现 Runnable,其 run 方法调用 runWorker。runWorker 在循环中先执行 firstTask,再不断从队列获取任务并执行 task.run();run 本身不再创建新线程,线程始终在同一 Thread 上循环处理任务直至关闭。于是同一线程被重复利用,完成线程复用的核心机制。

脏写、脏读、不可重复读和幻读

文章说明并发事务会产生脏写、脏读、不可重复读和幻读四类并发问题,并通过示例阐明其产生原因:未提交事务被其他事务读写导致数据回滚或结果不一致。随后介绍事务隔离机制和四种隔离级别(READ‑UNCOMMITTED、READ‑COMMITTED、REPEATABLE‑READ、SERIALIZABLE),说明各级别对上述现象的防护能力,并指出 MySQL 默认使用 REPEATABLE‑READ。

isAssignableFrom()方法与instanceof关键字

isAssignableFrom()和instanceof都用于类型判断,但侧重点不同。isAssignableFrom()在类层面比较,调用者是父类Class,参数是子类或自身Class,用于判断一个类是否可以赋值给另一个类;instanceof在实例层面比较,左侧是对象实例,右侧是其类或父类类型,用于判断对象是否是某类或其子类的实例。文章通过接口、父类、子类的代码示例展示两者的调用方式和输出结果,说明isAssignableFrom()判断“是否为父类”,instanceof判断“是否为子类”。

Spring AOP底层原理

Spring AOP 通过动态代理实现横向切面功能。若目标对象实现接口,Spring 使用 JDK Proxy 创建与接口同级的代理对象;若未实现接口,则采用 CGLIB 生成目标类的子类作为代理。代理对象在运行时拦截方法调用,实现与原实现类相同的功能,而无需修改源代码,从而完成 AOP 的横向扩展。

JVM之RTTI与反射

RTTI(运行时类型识别)通过获取 Class 对象来在运行时获取已知类的完整信息,获取方式包括 Class.forName、.class 和对象的 getClass(),前者会立即初始化类,后者在首次使用静态成员时才初始化。反射则用于编译时未知的类:在运行时加载对应的 .class 文件后,可通过 Class 的 getMethods、getConstructors 等获取 Method、Constructor 对象并实例化对象。核心区别在于 RTTI 需要编译期已知类名并在编译时检查 .class,而反射在运行时才打开并检查 .class,实现对未知类型的动态操作。

getField和getDeclaredField的区别

getField只能获取public字段并包括父类继承的成员,而getDeclaredField只能获取本类声明的所有字段(包括private),但不返回继承字段;对private字段需调用setAccessible(true)才能读写。示例中通过反射分别操作Person的private age和public money,得到相应的初始值并成功修改。文章还概括了反射的优点——运行时动态获取类、提升灵活性和可与动态编译结合实现强大功能;缺点——性能开销大、相对不安全且破坏封装。

常用设计模式

文章介绍了几种常用设计模式及其在业务代码中的实践。首先通过文件解析的例子说明 if…else 分支违背开闭原则和单一职责,提出策略模式的定义、接口抽象和基于 Spring 自动装配的实现方式。随后以订单校验为场景,指出使用异常做流程控制的问题,阐释责任链模式的概念、抽象处理器结构以及在 Spring 中通过注解和链式初始化完成各校验节点的组织。最后简要提出模板方法模式在统一请求流程(如商户信息查询、报文加签、HTTP 调用)中的作用。整体强调通过这些模式提升代码可维护性、可扩展性和职责分离。

JVM垃圾收集器ParNew&CMS与底层三色标记算法

文章介绍了JVM分代回收的基本原理,阐述了新生代采用复制算法、老年代使用标记‑清除或标记‑整理的原因,并详细比较了Serial、Parallel、ParNew、CMS等收集器的实现与适用场景。重点解析了CMS的四阶段并发标记、三色标记、写屏障及其产生的浮动垃圾、漏标问题,提供了ParNew+CMS在大流量电商系统中的参数调优方案,强调通过合理设置堆、Survivor、晋升阈值等可降低Full GC频率,提高响应时延。

Class对象的创建方式

本文演示了在 Java 中获取 Class 对象的五种常用方式:①通过实例调用 getClass();②使用 Class.forName(全限定名);③直接使用类字面量 .class;④通过基本类型包装类的 TYPE 字段获取原始类型 Class;⑤利用已有 Class 对象的 getSuperclass() 获取父类的 Class。代码示例分别展示了每种方法的使用及输出结果,帮助读者理解反射机制中 Class 对象的获取途径。

JVM垃圾收集器汇总

Serial 是单线程复制收集器,适用于 Client 模式小堆,停顿可接受;ParNew 为其多线程版,可配合 CMS 使用,在 Server 环境多 CPU 时提升并行度。Parallel Scavenge 同样是多线程复制收集器,侧重吞吐量,通过‑XX:GCTimeRatio、‑XX:MaxGCPauseMillis 调节;对应的老年代有 Serial Old(单线程标记‑整理)和 Parallel Old(多线程标记‑整理),后者与 Parallel Scavenge 组合实现高吞吐。CMS 采用并发标记‑清除,目标最短停顿,但对 CPU 敏感、产生碎片且无法处理浮动垃圾。G1 采用分区‑并行‑增量回收,提供可预测的停顿时间,调参主要是‑XX:MaxGCPauseMillis 等。整体上,JVM 提供了从单线程到并行、从低停顿到高吞吐的多种收集器,以满足不同应用场景的性能需求。

什么是桥接方法?

桥接方法是 JDK 1.5 为兼容泛型擦除后产生的编译器合成方法,字节码中标记为 ACC_BRIDGE 与 ACC_SYNTHETIC,可通过 Method.isBridge() 判断。它在以下情况下生成:①实现带泛型参数的接口,编译器为子类补充一个返回 Object、参数为 Object 的方法;②子类覆盖父类方法并使用协变返回类型(返回子类更具体的类型),编译器生成与父类签名相同的桥接方法。参数类型、数量、修饰符提升或 static 方法的覆盖都不会产生桥接方法。生成桥接方法的目的在于保持泛型代码在擦除后的二进制兼容性,使得在运行时通过父类或接口引用调用时仍能正确分派到子类实现,同时避免因类型不匹配而产生的运行时错误。