Java中创建对象的三种常见方式是new、反射和反序列化:new调用构造方法并触发类初始化;反射(如getDeclaredConstructor().newInstance())绕过编译检查但可能抛异常;反序列化不调用构造方法,跳过静态块和构造逻辑。

Java中对象创建的三种常见方式
Java里创建对象最常用的是new关键字,但实际开发中还会遇到反序列化、反射等场景,不同方式行为差异明显。
-
new ClassName():调用类的构造方法,触发类初始化(如果尚未初始化),是最直接、最可控的方式 -
Class.forName("ClassName").newInstance()(已弃用)或clazz.getDeclaredConstructor().newInstance():绕过编译期检查,适用于插件、框架扩展,但可能抛NoSuchMethodException或IllegalAccessException - 反序列化(
ObjectInputStream.readObject()):不调用任何构造方法,直接分配内存并填充字段值,因此静态块和构造逻辑不会执行——这点常被忽略,导致单例被破坏或资源未初始化
对象使用前必须确认类已加载与初始化
看似简单的new操作背后有明确的类加载阶段顺序:加载 → 验证 → 准备 → 解析 → 初始化。其中“初始化”阶段才执行static代码块和static变量赋值。
- 若类中含
static { System.out.println("init"); },首次new该类实例时才会输出,而非编译或第一次引用类名时 - 通过
Class.forName("X")默认会触发初始化;而ClassLoader.loadClass("X")不会——这是动态加载时控制初始化时机的关键区别 - 使用
javap -c查看字节码可验证:每个new指令后紧跟着dup和invokespecial(即构造方法调用)
常见错误:对象为null却直接调用方法
这不是语法错误,而是运行时NullPointerException的高发源头,尤其在依赖注入失败、条件分支遗漏或集合取值未判空时。
本书全面介绍PHP脚本语言和MySOL数据库这两种目前最流行的开源软件,主要包括PHP和MySQL基本概念、PHP扩展与应用库、日期和时间功能、PHP数据对象扩展、PHP的mysqli扩展、MySQL 5的存储例程、解发器和视图等。本书帮助读者学习PHP编程语言和MySQL数据库服务器的最佳实践,了解如何创建数据库驱动的动态Web应用程序。
- 不要写
obj.toString(),先做if (obj != null)或用Objects.toString(obj)(后者对null返回字符串"null") - Spring中
@Autowired字段为null,大概率是该类没走Spring容器管理(比如用new手动实例化),而非注解写错了 - 局部变量未显式初始化(如
String s;),编译直接报错;但成员变量会被默认初始化为null/0/false,容易掩盖逻辑缺陷
对象生命周期与引用类型的实际影响
Java对象是否被回收,不仅看new了多少次,更取决于可达性分析——而引用类型决定了GC时的处理策略。
立即学习“Java免费学习笔记(深入)”;
-
StrongReference(普通= new X()):只要强引用存在,GC绝不回收 -
WeakReference:GC时无论内存是否充足都会回收,适合做缓存(如WeakHashMap) -
SoftReference:内存不足时才回收,比弱引用“软”一点,曾用于图片缓存,但JDK 12+后回收策略更不可控,慎用 -
PhantomReference:无法通过它获取对象实例,仅用于跟踪对象被回收的时机,必须配合ReferenceQueue
WeakReference对象是否真正“可用”,取决于它有没有逃过GC、构造方法是否完整执行、以及所有依赖是否就绪——这些环节任何一个出问题,都可能让wr = new WeakReference<>(new String("hello")); System.gc(); // 不保证立即执行,但wr.get()很可能返回null
new出来的对象处于不可用状态。









