🚀 目录

  1. 开篇:那个被面试官问住的下午

  2. 方式一:最直观的 new 关键字(实干派)

    • 2.1 字节码层面的“魔法”

    • 2.2 JVM 视角:对象诞生的 5 个步骤

  3. 方式二:反射的魅力(动态派)

    • 3.1 Class.newInstance():逐渐远去的经典

    • 3.2 Constructor.newInstance():现在的真王

  4. 方式三:克隆的力量(复制派)

    • 4.1 为什么克隆不调用构造函数?

    • 4.2 性能优化的“黑捷径”

  5. 补充包:那些“不按套路出牌”的创建方式

    • 5.1 反序列化:从流中“复活”

    • 5.2 Unsafe 类的“上帝视角”

  6. 核心对比:一张表教你做人

  7. 结语:拒绝只会 new,做有深度的开发者

1. 开篇:那个被面试官问住的下午

坐标:学校图书馆 2 楼(靠窗,阳光有点晒,但我心很冷)

状态:拿着刚打印的简历,回想起模拟面试时的尴尬。

碎碎念: 兄弟们,今天我彻底破防了。 模拟面试的时候,面试官问我:“除了 new 之外,Java 还有哪些创建对象的方式?” 我当时脑子里第一反应是:“不 new 怎么创建?难道用意念吗?”

结果面试官推了推眼镜,幽幽地来了一句:“如果你连反射和克隆创建对象的底层区别都说不清楚,那你的 JVM 算是白学了。”

痛定思痛,我翻了一下午的《深入理解 Java 虚拟机》。原来在 Java 的世界里,生孩子(创建对象)的方法远不止一种。今天咱就来深度解剖一下这 3 种核心方式,顺便带大家看看 JVM 到底是怎么干活的!

2. 方式一:最直观的 new 关键字(实干派)

这是我们大学第一天学 Java 就会的姿势:Student s = new Student();

2.1 字节码层面的“魔法”

你以为这一行代码很简单?但在 JVM 眼里,它对应了好几条指令。最核心的是 newinvokespecial

  • new:负责在堆内存里开辟空间,并返回一个指向该空间的引用。

  • invokespecial:负责调用构造方法(<init>),完成初始化。

2.2 JVM 视角:对象诞生的 5 个步骤

  1. 类加载检查:看看这个类有没有被加载过,没有就得先走加载流程。

  2. 分配内存:根据对象大小在堆里划出一块地。

  3. 零值初始化:先把所有变量清零(int 变成 0,boolean 变成 false)。这也是为什么你不给属性赋值,它也有默认值的原因。

  4. 设置对象头:记录这个对象是谁、它的 Hash 码、它的 GC 分代年龄等。

  5. 执行构造方法:真正的初始化开始,把属性改成你想要的值。

3. 方式二:反射的魅力(动态派)

反射是很多框架(比如 Spring)的灵魂。

3.1 Class.newInstance():逐渐远去的经典

Student s = Student.class.newInstance();

这种方式只能调用无参构造器,而且如果构造器是 private 的,它就直接歇菜了。所以 Java 9 之后已经不推荐用了。

3.2 Constructor.newInstance():现在的真王

Constructor<Student> constructor = Student.class.getConstructor(String.class);
Student s = constructor.newInstance("林北");

这才是大佬用的方式!它可以调用任何构造器,甚至是 private 的(只要你调用 setAccessible(true))。它更安全,处理异常也更专业。

4. 方式三:克隆的力量(复制派)

如果你已经有一个对象了,想再要一个一模一样的,那就用 clone()

4.1 为什么克隆不调用构造函数?

这是一个极高频的面试点! clone() 的本质是内存拷贝。它直接从内存里把原对象的二进制流复制一份到新地址。既然是直接拷贝内存,它就不需要去走那套繁琐的“调用构造函数”的流程。

4.2 性能优化的“黑捷径”

如果你要创建一个非常复杂的对象,里面的属性多到爆炸,构造函数里还有一堆逻辑,那用 clone() 的效率会比 new 高得多。

5. 补充包:那些“不按套路出牌”的方式

既然是为了 5000 字量级(吹水深度)准备的,咱们得聊聊这两个黑科技:

5.1 反序列化:从流中“复活”

当你从文件或者网络中读取一个对象时,JVM 同样不会调用构造函数。它通过保存的字节流直接在堆中重建对象状态。

5.2 Unsafe 类的“上帝视角”

sun.misc.Unsafe 有个方法叫 allocateInstance。它直接在堆上开辟内存并返回引用,不仅不调用构造函数,连类初始化都不管。除非你在写高性能中间件,否则业务代码里用这个会被开除的。

6. 核心对比:一张表教你做人

方式

语法

是否调用构造器

适用场景

new

new X()

99% 的日常开发

反射

newInstance()

Spring 等框架、动态加载

clone

obj.clone()

原型模式、追求极致性能

反序列化

readObject()

网络传输、对象持久化

Unsafe

allocateInstance()

极高性能场景、写框架黑科技

7. 结语

从最基础的 new 到神秘的 Unsafe,Java 为我们提供了多样的对象创建姿势。

作为大学生的我们:

  • 要知道 new 是规矩。

  • 要明白 反射 是灵魂。

  • 要理解 clone 是捷径。

掌握了这些,下次面试官再问你,你就可以淡定地抿一口冰美式,然后从 JVM 指令集一直聊到内存地址分配。

如果你觉得这篇笔记救了你的面试,点个赞支持一下!下期咱们聊聊自动装箱与自动拆箱

更多推荐