加载中

Java

文章分类

浏览该分类下的所有文章

237 篇文章 20

如何避免创建不必要的对象?

在 Java 开发中,应尽量避免创建功能相同的对象以节省内存和提升性能。使用字符串常量池代替 `new String`,在循环中复用同一 `String`;根据需求选用 `String`(不可变)、`StringBuilder`(可变、单线程)或 `StringBuffer`(线程安全)。对布尔值使用 `Boolean.valueOf` 而非 `new Boolean`,因为前者直接返回已缓存的实例。尽量避免自动装箱/拆箱导致的对象创建,优先使用基本类型 `int` 而非包装类 `Integer`。正则表达式应先 `Pattern.compile` 再复用匹配器,避免在循环中重复编译。上述技巧均可显著降低对象创建次数,提升程序运行效率。

如何正确的释放资源?

文章指出传统的 try‑catch‑finally 方式关闭 I/O 流代码冗长且易漏关闭,推荐使用 Java 7 的 try‑with‑resources,前提是资源实现 AutoCloseable。示例展示了改写前后对比,代码更简洁、可读性高,且自动释放资源,避免手动关闭时的顺序和异常处理问题。文中还提供了一个可变参数的 close 方法作为备选,但强调最优解仍是 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,得到相应的初始值并成功修改。文章还概括了反射的优点——运行时动态获取类、提升灵活性和可与动态编译结合实现强大功能;缺点——性能开销大、相对不安全且破坏封装。

常用设计模式

文章介绍了几种常用设计模式在业务代码中的实际使用。先以文件解析的多分支示例说明违反开闭原则和单一职责,提出使用策略模式将不同解析实现封装为统一接口的类,并通过 Spring 自动装配构建策略映射,实现扩展无修改。再以订单校验为例指出异常不宜做流程控制,阐述责任链模式的概念与实现:抽象处理器、各具体校验节点以及链式初始化,使校验逻辑解耦且可灵活排序。最后简要提及模板方法模式在统一业务流程(如商户调用第三方)中的应用,强调通过抽象父类定义固定步骤、子类实现细节以复用公共流程。

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 提供了从单线程到并行、从低停顿到高吞吐的多种收集器,以满足不同应用场景的性能需求。