[Java学习日记12】聊聊创建对象的三种方式
🚀 目录
-
-
2.1 字节码层面的“魔法”
-
2.2 JVM 视角:对象诞生的 5 个步骤
-
-
-
3.1 Class.newInstance():逐渐远去的经典
-
3.2 Constructor.newInstance():现在的真王
-
-
-
4.1 为什么克隆不调用构造函数?
-
4.2 性能优化的“黑捷径”
-
-
-
5.1 反序列化:从流中“复活”
-
5.2 Unsafe 类的“上帝视角”
-
1. 开篇:那个被面试官问住的下午
坐标:学校图书馆 2 楼(靠窗,阳光有点晒,但我心很冷)
状态:拿着刚打印的简历,回想起模拟面试时的尴尬。
碎碎念: 兄弟们,今天我彻底破防了。 模拟面试的时候,面试官问我:“除了
new之外,Java 还有哪些创建对象的方式?” 我当时脑子里第一反应是:“不new怎么创建?难道用意念吗?”结果面试官推了推眼镜,幽幽地来了一句:“如果你连反射和克隆创建对象的底层区别都说不清楚,那你的 JVM 算是白学了。”
痛定思痛,我翻了一下午的《深入理解 Java 虚拟机》。原来在 Java 的世界里,生孩子(创建对象)的方法远不止一种。今天咱就来深度解剖一下这 3 种核心方式,顺便带大家看看 JVM 到底是怎么干活的!
2. 方式一:最直观的 new 关键字(实干派)
这是我们大学第一天学 Java 就会的姿势:Student s = new Student();
2.1 字节码层面的“魔法”
你以为这一行代码很简单?但在 JVM 眼里,它对应了好几条指令。最核心的是 new 和 invokespecial。
-
new:负责在堆内存里开辟空间,并返回一个指向该空间的引用。 -
invokespecial:负责调用构造方法(<init>),完成初始化。
2.2 JVM 视角:对象诞生的 5 个步骤
-
类加载检查:看看这个类有没有被加载过,没有就得先走加载流程。
-
分配内存:根据对象大小在堆里划出一块地。
-
零值初始化:先把所有变量清零(int 变成 0,boolean 变成 false)。这也是为什么你不给属性赋值,它也有默认值的原因。
-
设置对象头:记录这个对象是谁、它的 Hash 码、它的 GC 分代年龄等。
-
执行构造方法:真正的初始化开始,把属性改成你想要的值。
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 |
|
是 |
99% 的日常开发 |
|
反射 |
|
是 |
Spring 等框架、动态加载 |
|
clone |
|
否 |
原型模式、追求极致性能 |
|
反序列化 |
|
否 |
网络传输、对象持久化 |
|
Unsafe |
|
否 |
极高性能场景、写框架黑科技 |
7. 结语
从最基础的 new 到神秘的 Unsafe,Java 为我们提供了多样的对象创建姿势。
作为大学生的我们:
-
要知道
new是规矩。 -
要明白
反射是灵魂。 -
要理解
clone是捷径。
掌握了这些,下次面试官再问你,你就可以淡定地抿一口冰美式,然后从 JVM 指令集一直聊到内存地址分配。
如果你觉得这篇笔记救了你的面试,点个赞支持一下!下期咱们聊聊自动装箱与自动拆箱
更多推荐
所有评论(0)