【Java.八股】Java对象到底是怎么创建出来的,从new到GC回收,一篇彻底讲透(建议收藏)

张开发
2026/6/13 16:11:34 15 分钟阅读

分享文章

【Java.八股】Java对象到底是怎么创建出来的,从new到GC回收,一篇彻底讲透(建议收藏)
个人主页代码不加冰欢迎来访作者简介java后端学习者❄️个人专栏LeetCode刷题日记 苍穹外卖日记SSM框架深入JavaWeb✨命运的结局尽可永在不屈的挑战却不可须臾或缺前言大家好我是代码不加冰嗯今天和昨天上午沉迷于国外软件这几天注册了好几个谷歌邮箱顺便也弄了个电报油管这些软件感觉还挺有意思的现在收收心继续开始学习这里主要是java的基础八股让我们一起来看看吧。摘要本文详细讲解了Java中对象的创建方式及其底层机制涵盖new、反射、克隆、反序列化、工厂模式和单例模式6种方法并解析了对象生命周期和垃圾回收原理。特别强调new创建对象时JVM自动调用构造方法的细节以及单例模式通过私有构造器和静态实例保证唯一性的实现。文章还总结了面试常见问题包括对象回收时机、私有对象获取方式等指出对象变为垃圾的条件是失去所有引用但回收由JVM决定。最后提到反射可以突破private限制获取对象而单例模式通过getInstance()方法提供受控访问。适合Java初学者系统理解对象创建机制和面试准备。对于刚学习 Java 的同学来说对象绝对是最核心的概念之一。很多人在刚接触 Java 时经常会有这样的疑问什么是对象为什么要创建对象Java 中对象到底是怎么创建出来的除了new之外还有其他方式吗本文将从 Java 新手的视角出发通过大量实例详细讲解 Java 中对象创建的各种方式让你真正理解对象的创建过程同时附上面试会遇到的经典八股一、什么是对象在 Java 中一切皆对象Everything is Object。现实生活中的事物都可以抽象成对象。例如人汽车手机学生都可以看作对象。假设我们定义一个学生类public class Student { String name; int age; public void study() { System.out.println(name 正在学习); } }这里的Student只是一个模板类。真正存在的数据需要通过创建对象得到。例如Student s new Student();此时s就是一个真正的学生对象。谁调用了构造方法表面上看new Student();并没有写Student();或者s.Student();这样的代码。但实际上new Student();这条语句中就包含了对构造方法的调用。JVM帮你调用了当执行Student s new Student();JVM大致会做下面几步第一步申请内存在堆中创建Student对象堆 Student对象 name null第二步执行构造方法JVM发现public Student() { System.out.println(对象创建成功); }于是自动调用Student()执行System.out.println(对象创建成功);输出对象创建成功第三步返回对象引用创建完成后返回地址Student s new Student();变成s ↓ Student对象为什么不能手动调用构造方法很多新手会尝试Student s new Student(); s.Student(); // 错误编译直接报错。因为Student()虽然长得像方法但它本质上不是普通方法。它属于构造器Constructor只能在new Student()时由 JVM 自动调用。编译后的真实情况很多人以为new Student();就是一个语法。实际上编译成字节码后会变成new dup invokespecial Student.init()其中init()就是构造方法。也就是说 JVM 真正执行了Student.init()只是这个过程对程序员隐藏了。面试回答如果面试官问构造方法是谁调用的标准回答构造方法由 JVM 在对象创建过程中自动调用。程序员不能像普通方法一样直接调用构造方法。当执行new Student()时JVM先为对象分配内存然后调用构造方法init()完成对象初始化最后返回对象引用。二、通过反射创建对象什么是反射反射Reflection是 Java 的高级特性。它允许程序运行时动态创建对象。普通创建Student student new Student();编译时已经知道类名。反射创建Class clazz Class.forName(Student); Student student (Student) clazz.newInstance();或者ClassStudent clazz Student.class; Student student clazz.getDeclaredConstructor() .newInstance();示例public class Test { public static void main(String[] args) throws Exception { ClassStudent clazz Student.class; Student student clazz.getDeclaredConstructor() .newInstance(); System.out.println(student); } }使用场景框架大量使用SpringSpringBootMyBatisHibernate例如 Spring 容器启动时Controller Service Repository背后很多对象就是通过反射创建的。三、通过clone()创建对象什么是克隆克隆相当于复制一个对象。类似原件 → 复印件第一步实现 Cloneable 接口public class Student implements Cloneable { String name; Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }第二步克隆对象Student s1 new Student(); s1.name 张三; Student s2 (Student)s1.clone();验证System.out.println(s1 s2);结果false说明s1 s2是两个不同对象。内存图s1 ──► Student(name张三) s2 ──► Student(name张三)使用场景当对象创建成本很高时配置对象 数据库连接配置 游戏角色模板可以直接复制已有对象。四、通过反序列化创建对象这是很多面试题会问到的知识点。序列化对象保存到文件。ObjectOutputStream反序列化从文件恢复对象。ObjectInputStream保存对象Student s new Student(); ObjectOutputStream out new ObjectOutputStream( new FileOutputStream(a.txt)); out.writeObject(s);恢复对象ObjectInputStream in new ObjectInputStream( new FileInputStream(a.txt)); Student student (Student) in.readObject();注意反序列化时不会调用构造方法这是面试中经常考察的点。五、通过工厂模式创建对象实际开发中很少直接new UserService();更多会使用工厂模式。普通创建UserService service new UserService();工厂创建public class ServiceFactory { public static UserService getService() { return new UserService(); } }使用UserService service ServiceFactory.getService();这里使用的是静态方法可以直接类名调用方法这里需要主要容易搞混。Message message new SmsMessage();创建的是什么对象正确回答创建的是SmsMessage对象。Message只是引用类型用来接收对象引用。对象的实际类型由new后面的类决定而不是由左边变量类型决定。记住一句话左边决定能调用什么方法编译期 右边决定实际是什么对象运行期这就是 Java 多态最核心的一句话。优势用户不需要知道对象怎么创建只需要拿来用工厂模式是一种创建型设计模式它将对象的创建逻辑封装起来客户端无需直接使用 new从而降低耦合。单例模式也是创建型设计模式它通过私有构造器和静态实例保证一个类在 JVM 中通常只有一个实例并提供全局访问点。六、通过单例模式获取对象单例模式保证一个类只有一个对象单例模式通常包含三个核心部分私有化构造方法private Constructor防止外部通过 new 创建对象。私有静态实例private static Instance在类内部保存唯一实例保证全局只有一个对象。公共静态获取方法public static getInstance向外提供获取唯一实例的入口。其核心思想是控制对象创建过程 确保一个类在 JVM 中通常只有一个实例 并提供全局访问点。public class Singleton { private Singleton() {} private static final Singleton INSTANCE new Singleton(); public static Singleton getInstance() { return INSTANCE; } }整句代码的意思instance 是一个静态成员变量类型为 Singletonnew Singleton() 创建了一个 Singleton 对象instance 中保存的是该对象的引用地址通过这个引用可以访问唯一的 Singleton 实例。private static Singleton instance new Singleton();相当于Singleton instance; instance new Singleton();意思创建一个Singleton类型变量instance 再创建一个Singleton对象 让instance指向这个对象使用Singleton s Singleton.getInstance();验证Singleton s1 Singleton.getInstance(); Singleton s2 Singleton.getInstance(); System.out.println(s1 s2);结果true说明始终是同一个对象七、匿名对象匿名对象就是没有变量接收的对象例如new Student();或者new Student().study();示例new Student().study();输出正在学习特点对象创建后立即使用。使用完后没有引用指向它很快会被垃圾回收。八、面试常问new一个对象到底发生了什么例如Student student new Student();JVM会执行① 类加载检查确认 Student 类已经加载。② 分配内存在堆中开辟空间。③ 初始化默认值name null age 0④ 设置对象头保存哈希码锁信息GC信息等。⑤ 调用构造方法public Student() { }⑥ 返回引用地址student指向创建好的对象。九、各种对象创建方式总结创建方式是否常用是否调用构造方法new★★★★★是反射★★★★☆是clone★★★☆☆否反序列化★★★☆☆否工厂模式★★★★☆最终会调用单例模式★★★★★初始化时调用匿名对象★★★☆☆是总结对于 Java 新手来说最需要掌握的是以下三种new 创建对象必须掌握反射创建对象框架核心单例模式获取对象面试高频十、New出来的对象什么时候消失这个问题已经开始接触 JVM 和垃圾回收GC了也是面试高频题。先说结论Student s new Student();这里new出来的对象不是用完立即回收也不是程序结束才回收。而是当对象没有任何引用指向它时 它就会变成垃圾对象 等待GC垃圾回收器回收。例1最简单的情况Student s new Student();内存s ↓ Student对象A此时对象A 有引用指向GC不能回收。例2引用断开Student s new Student(); s null;执行后s null而对象Student对象A已经没人指向了。变成垃圾对象此时可以被GC回收注意可以回收 ≠ 立即回收很多人误解s null;下一秒对象就没了。不是。只是告诉 JVM这个对象已经没用了什么时候真正回收由GC决定例3引用被覆盖Student s new Student();内存s ↓ 对象A然后s new Student();发生创建对象B变成s ↓ 对象B而对象A没人指向了。于是对象A成为垃圾等待回收。例4方法结束public void test() { Student s new Student(); }执行时栈 ↓ s 堆 ↓ Student对象方法结束test();返回后栈帧销毁变量s消失。此时Student对象没有引用指向。变成垃圾对象。十一、JVM怎么判断对象能不能回收很多新手以为引用计数法实际上 Java HotSpot JVM 主要使用可达性分析算法GC RootJVM会从GC Root 开始找。例如Student s new Student();局部变量s就是一个 Root。内存GC Root ↓ s ↓ 对象A对象A可达。不能回收。如果s null;变成GC Root s null 对象A已经找不到对象A。于是对象A不可达可以回收。十二、面试中的经典回答面试官new 出来的对象什么时候回收标准回答Java 中 new 创建的对象存放在堆内存中。当对象不再被任何 GC Root 可达时会被判定为垃圾对象等待垃圾回收器GC回收。对象变成垃圾并不意味着立即回收具体回收时间由 JVM 的垃圾回收机制决定。如何获取一个 private 私有对象不要直接回答get方法初级回答如果一个对象被定义为私有成员private User user new User();通常通过公开方法访问public User getUser() { return user; }外部User user obj.getUser();获取对象。面试标准回答private 只限制类外直接访问不限制类内访问。因此通常通过 public 方法Getter、工厂方法、单例的 getInstance 方法等间接返回私有对象的引用从而实现封装。例如public class Singleton { private static Singleton instance new Singleton(); public static Singleton getInstance() { return instance; } }外部通过Singleton.getInstance();获取私有对象。面试官继续追问private 对象真的无法获取吗这时候要答正常情况下只能通过公开方法访问但 Java 反射机制可以突破访问权限限制。通过setAccessible(true)可以访问 private 字段、方法甚至构造器。例如Field field Singleton.class.getDeclaredField(instance); field.setAccessible(true); Singleton instance (Singleton) field.get(null);面试加分点如果面试官问的是单例模式中的 private 对象如何获取回答单例模式会将实例对象定义为 private static防止外部直接访问然后通过 public static getInstance() 方法返回唯一实例实现受控访问。例如private static Singleton instance new Singleton(); public static Singleton getInstance() { return instance; }八股文版private 修饰的对象无法被类外直接访问但可以通过类内部提供的 public 方法间接获取其引用这体现了封装思想。除此之外Java 的反射机制也可以突破访问控制通过setAccessible(true)访问 private 成员。在单例模式中通常通过public static getInstance()方法获取 private static 实例对象。结语如果对你有帮助请点赞关注收藏你的支持就是我最大的鼓励

更多文章