发布时间:2026/7/13 0:40:27
Java 大厂面试高频题:别再只会 new 了!Java 创建对象竟然有这么多种方式 在学习 Java 时我们最先接触的对象创建方式通常是PersonpersonnewPerson();因此很多初学者会认为 Java 创建对象只能使用new。实际上Java 中常见的对象创建方式不止一种。除了直接使用new还可以通过反射、克隆、反序列化、工厂方法等方式获得对象。本文将介绍 Java 中常见的 6 种对象创建方式1. 使用 new 关键字 2. 使用反射调用构造方法 3. 使用 Class.newInstance() 4. 使用 clone() 克隆对象 5. 使用反序列化创建对象 6. 使用工厂方法获得对象在理解这些方式之前需要先明确对象、引用变量和类不是同一个概念。一、什么是创建对象先定义一个简单的Person类classPerson{privateStringname;publicPerson(){System.out.println(Person 构造方法执行了);}publicPerson(Stringname){this.namename;System.out.println(有参构造方法执行了);}publicvoidsayHello(){System.out.println(你好我是name);}}创建对象时通常写PersonpersonnewPerson();这句代码可以拆成三部分Person变量的类型 person引用变量 new Person()创建 Person 对象真正创建出来的对象是newPerson()person只是一个引用变量它保存了对这个对象的引用。可以类比为Person 类房屋设计图 Person 对象根据设计图建出的房子 person 变量房子的门牌号接下来看看 Java 创建对象的不同方式。二、方式一使用 new 关键字使用new是最常见、最直接的对象创建方式。PersonpersonnewPerson();也可以调用有参构造方法PersonpersonnewPerson(张三);执行new Person(张三)时Java 大致会完成以下操作1. 在堆内存中为 Person 对象分配空间 2. 为成员变量设置默认值 3. 执行成员变量的显式初始化 4. 执行构造代码块 5. 调用对应的构造方法 6. 返回新对象的引用。使用publicclassTest{publicstaticvoidmain(String[]args){PersonpersonnewPerson(张三);person.sayHello();}}输出有参构造方法执行了 你好我是张三特点语法简单 可读性强 会调用构造方法 是日常开发中最常用的方式。大多数情况下创建普通业务对象都应该优先使用new。三、方式二使用反射调用构造方法反射允许程序在运行过程中动态获取类的信息并创建对象。推荐使用Constructor.newInstance()示例importjava.lang.reflect.Constructor;publicclassTest{publicstaticvoidmain(String[]args)throwsException{ClassPersonclazzPerson.class;ConstructorPersonconstructorclazz.getDeclaredConstructor(String.class);Personpersonconstructor.newInstance(李四);person.sayHello();}}输出有参构造方法执行了 你好我是李四代码解释如下。首先获取Person的Class对象ClassPersonclazzPerson.class;然后获取参数为String的构造方法ConstructorPersonconstructorclazz.getDeclaredConstructor(String.class);最后通过构造方法创建对象Personpersonconstructor.newInstance(李四);如果要调用无参构造方法可以写ConstructorPersonconstructorPerson.class.getDeclaredConstructor();Personpersonconstructor.newInstance();为什么需要反射创建对象因为有些场景在编写代码时并不知道最终要创建哪个类。例如配置文件中写着com.example.service.UserService程序运行时读取这个类名再动态创建对象。很多框架内部都大量使用了反射例如Spring Spring Boot MyBatis Hibernate JUnit JacksonSpring 扫描到一个带有Service注解的类后可以通过反射创建它的对象并交给 IoC 容器管理。特点可以动态决定创建哪个类 可以调用无参或有参构造方法 适合框架和底层工具开发 代码比 new 复杂 反射调用通常比直接 new 慢。在现代 Java 中通过反射创建对象时通常推荐使用Constructor.newInstance()。四、方式三使用 Class.newInstance()以前还可以通过Class对象的newInstance()方法创建对象PersonpersonPerson.class.newInstance();或者Class?clazzClass.forName(Person);Personperson(Person)clazz.newInstance();这段代码会调用Person的无参构造方法。但是这种方式存在明显限制只能调用无参构造方法 异常处理不够清晰 无法灵活选择构造方法 该方法已经被废弃。因此现在不建议继续使用clazz.newInstance();推荐改成PersonpersonPerson.class.getDeclaredConstructor().newInstance();也就是说Class.newInstance()可以作为面试知识点了解但新项目中应该使用Constructor.newInstance()。五、方式四使用 clone() 克隆对象clone()的作用不是从零开始创建一个全新状态的对象而是根据已有对象复制出一个新对象。首先让类实现Cloneable接口classPersonimplementsCloneable{privateStringname;publicPerson(Stringname){this.namename;System.out.println(构造方法执行了);}publicStringgetName(){returnname;}OverridepublicPersonclone()throwsCloneNotSupportedException{return(Person)super.clone();}}使用publicclassTest{publicstaticvoidmain(String[]args)throwsCloneNotSupportedException{Personp1newPerson(王五);Personp2p1.clone();System.out.println(p1p2);System.out.println(p2.getName());}}输出构造方法执行了 false 王五注意构造方法只执行了一次。执行Personp2p1.clone();时并不会再次调用Person的构造方法。同时p1p2结果为false说明p1和p2指向两个不同的对象。clone() 默认是浅拷贝如果Person中包含一个引用类型成员classAddress{Stringcity;}classPersonimplementsCloneable{Stringname;Addressaddress;OverridepublicPersonclone()throwsCloneNotSupportedException{return(Person)super.clone();}}执行Personp2p1.clone();会得到p1 和 p2 是不同的 Person 对象 p1.address 和 p2.address 指向同一个 Address 对象。也就是说super.clone()默认实现的是浅拷贝。如果需要深拷贝还需要继续复制内部对象。特点根据已有对象复制新对象 通常不会调用构造方法 默认是浅拷贝 需要实现 Cloneable 适合复制已有对象状态。六、方式五使用反序列化创建对象序列化是把对象转换成字节数据反序列化则是把字节数据恢复成对象。首先让类实现Serializableimportjava.io.Serializable;classPersonimplementsSerializable{privatestaticfinallongserialVersionUID1L;privateStringname;publicPerson(Stringname){this.namename;System.out.println(构造方法执行了);}publicStringgetName(){returnname;}}把对象序列化到文件importjava.io.FileOutputStream;importjava.io.ObjectOutputStream;PersonpersonnewPerson(赵六);try(ObjectOutputStreamoutputnewObjectOutputStream(newFileOutputStream(person.dat))){output.writeObject(person);}再通过反序列化恢复对象importjava.io.FileInputStream;importjava.io.ObjectInputStream;Personperson;try(ObjectInputStreaminputnewObjectInputStream(newFileInputStream(person.dat))){person(Person)input.readObject();}System.out.println(person.getName());反序列化会根据文件中的数据重新创建一个Person对象。对于普通实现了Serializable的类反序列化时通常不会调用该可序列化类的构造方法。使用场景反序列化常见于读取持久化对象 网络传输 缓存恢复 消息通信 对象深拷贝。不过Java 原生序列化存在性能、安全性和兼容性方面的问题。现代项目中更常见的是使用JSON Protocol Buffers Kryo Avro等格式传输或保存数据。特点根据已有的字节数据恢复对象 通常不会调用当前类的构造方法 类需要实现 Serializable 可能存在安全和版本兼容问题。不要反序列化不可信来源的数据否则可能带来安全风险。七、方式六使用工厂方法获得对象工厂方法是实际开发中非常常见的一种对象获取方式。例如classPerson{privateStringname;privatePerson(Stringname){this.namename;}publicstaticPersoncreate(Stringname){returnnewPerson(name);}}使用PersonpersonPerson.create(小明);表面上没有直接使用new而是通过Person.create()获得对象。不过需要注意工厂方法内部可能仍然使用了newreturnnewPerson(name);因此从 JVM 底层角度看最终可能还是由new创建对象但从调用者角度看对象是通过工厂方法获得的。工厂方法有什么好处1. 方法名更清晰Person.createAdmin();Person.createGuest();Person.fromDatabase(data);比多个含义不清晰的构造方法更容易理解。2. 可以返回缓存对象例如IntegeraInteger.valueOf(100);IntegerbInteger.valueOf(100);Integer.valueOf()可能返回缓存中的已有对象而不是每次都创建新对象。3. 可以返回子类对象AnimalanimalAnimalFactory.create(dog);工厂内部可以根据参数返回newDog()或者newCat()调用者不需要关心具体实现类。4. 可以统一控制创建过程工厂方法可以加入参数校验 缓存 对象池 权限检查 日志记录 依赖注入。常见例子Java 中有很多工厂方法Integer.valueOf(10);List.of(A,B);LocalDate.of(2026,7,12);Optional.of(Java);Executors.newFixedThreadPool(5);特点隐藏对象创建细节 方法名可以表达业务含义 可以返回缓存对象或子类对象 有利于降低代码耦合 内部不一定每次都创建新对象。严格来说“通过工厂方法获得对象”不一定意味着每次都创建了新对象因为它可能返回已有对象。八、使用 Unsafe 创建对象Java 底层还存在一种特殊方式通过Unsafe分配对象。概念上可以写成Personperson(Person)unsafe.allocateInstance(Person.class);它可以直接为对象分配内存但不会正常调用构造方法。Unsafe属于底层内部 API可能破坏 Java 的封装性和对象初始化规则一般业务开发中不应该使用。它更可能出现在JVM 底层工具 高性能框架 序列化框架 代理框架 特殊测试场景。对于初学者只需要知道这种方式存在即可不建议实际使用。九、这些方式是否都会调用构造方法不同创建方式对构造方法的调用情况不同。创建方式是否调用构造方法常见用途new会普通对象创建Constructor.newInstance()会反射、框架Class.newInstance()会调用无参构造旧式反射不推荐clone()通常不会复制已有对象反序列化当前可序列化类通常不会恢复对象工厂方法取决于内部实现封装创建逻辑Unsafe.allocateInstance()不会底层框架这是面试中经常考察的一个重点使用new和反射调用构造器会执行构造方法使用clone()和普通反序列化恢复当前类对象时通常不会调用该类构造方法。十、创建对象和获得对象有什么区别严格来说有些方式是“真正创建新对象”有些方式只是“获得一个对象”。例如IntegernumberInteger.valueOf(100);valueOf()可能返回缓存中的已有对象因此不保证一定创建新对象。再例如 SpringUserServiceuserServiceapplicationContext.getBean(UserService.class);这里是从 Spring 容器获取对象对象可能早已创建完成并不是此时才创建。因此下面两种说法存在细微区别创建对象明确产生一个新的对象实例 获得对象拿到一个对象引用可能是新对象也可能是已有对象。不过在初级面试题中工厂方法、Spring 容器等方式经常也会被归入“对象创建方式”进行讨论。十一、实际开发应该选择哪种方式普通业务对象优先使用newPerson();代码直观、简单。框架动态创建对象使用反射clazz.getDeclaredConstructor().newInstance();复制已有对象可以使用拷贝构造方法 clone() 手动字段复制。相比clone()很多项目更喜欢使用拷贝构造方法因为逻辑更加明确PersoncopiednewPerson(original);从文件、缓存或网络恢复对象可以使用反序列化但实际项目中通常优先考虑 JSON、Protobuf 等方案。隐藏复杂创建逻辑使用工厂方法PersonpersonPersonFactory.create(type);十二、常见面试问题1. Java 创建对象有哪些方式可以回答Java 创建或获得对象的常见方式包括使用 new 关键字、使用反射调用构造方法、通过 clone() 克隆对象、通过反序列化恢复对象以及通过静态工厂方法或工厂模式获得对象。其中Class.newInstance() 已经被废弃反射创建对象推荐使用 Constructor.newInstance()。2. 哪些方式不会调用构造方法可以回答使用 clone() 克隆对象通常不会调用构造方法通过 Java 反序列化恢复当前可序列化类对象时通常也不会调用该类构造方法Unsafe.allocateInstance() 同样不会调用构造方法。3. newInstance() 推荐使用哪一个推荐clazz.getDeclaredConstructor().newInstance();不推荐clazz.newInstance();因为后者已经被废弃并且只能调用无参构造方法。十三、总结Java 中常见的对象创建或获取方式包括1. new最常用会调用构造方法 2. Constructor.newInstance()通过反射调用构造方法 3. Class.newInstance()旧式反射方式已经废弃 4. clone()复制已有对象通常不调用构造方法 5. 反序列化从字节数据恢复对象 6. 工厂方法隐藏创建细节可能创建新对象也可能返回已有对象 7. Unsafe底层特殊方式不建议普通开发使用。初学者最需要掌握的是new 反射 clone 反序列化 工厂方法最后用一句话概括Java 创建对象不只有new还可以通过反射、克隆、反序列化和工厂方法等方式获得对象它们最大的区别在于创建过程是否调用构造方法、是否依赖已有对象以及是否真正生成新的对象实例。

相关新闻

2026/7/13 0:40:27

Git bundle 与 tar/zip 备份对比:2种方案性能与完整性实测

Git Bundle 与 Tar/Zip 备份方案深度对比:性能与完整性实测报告在代码版本管理和数据备份领域,Git bundle 和传统的文件系统打包工具(如 tar、zip)是两种截然不同的技术路线。本文将通过 12 项核心指标的系统性测试,揭…

2026/7/13 0:40:27

VS Code C# Dev Kit 1.0 配置指南:5个必装插件与 .NET 8 项目创建实战

VS Code C# Dev Kit 1.0 配置指南:5个必装插件与 .NET 8 项目创建实战微软最新推出的C# Dev Kit扩展包彻底改变了VS Code的.NET开发体验。作为从Visual Studio迁移过来的老用户,我发现这套工具链不仅保留了VS的核心功能,还带来了更轻量高效的…

2026/7/13 2:00:31

C++高精度阶乘实现:从数组模拟到压位优化与FFT进阶

1. 项目概述:从“为什么没有”到“如何实现”在C的日常开发中,我们经常会遇到需要计算阶乘的场景,比如组合数学、概率统计,或者一些算法题。很多初学者会下意识地在标准库中寻找一个像std::factorial这样的函数,结果当…

2026/7/13 2:00:31

C#ADO编程的关键类

一、思维导图ADO.NET 核心类体系├── SqlConnection(数据库连接类)│ ├── 属性:ConnectionString / State / Database / DataSource / ConnectionTimeout│ ├── 方法:Open() / Close() / Dispose() / CreateCommand()…

2026/7/12 0:01:29

3步解锁音乐自由:ncmdumpGUI终极NCM文件解密转换指南

3步解锁音乐自由:ncmdumpGUI终极NCM文件解密转换指南 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾在网易云音乐下载了心爱的歌曲&#…

2026/7/12 0:01:29

CANoe 19 SP3 配置 GB/T 27930-2023 A类系统:3步搭建BMS仿真测试环境

CANoe 19 SP3 配置 GB/T 27930-2023 A类系统:3步搭建BMS仿真测试环境随着新能源汽车行业的快速发展,充电通信协议的标准化和测试验证变得尤为重要。GB/T 27930-2023作为中国智能充电协议的最新版本,对充电机与电动汽车之间的通信提出了更严格…

2026/7/12 0:01:29

3步搞定RTL8852BE驱动:从零开始配置Wi-Fi 6网卡

3步搞定RTL8852BE驱动:从零开始配置Wi-Fi 6网卡 【免费下载链接】rtl8852be Realtek Linux WLAN Driver for RTL8852BE 项目地址: https://gitcode.com/gh_mirrors/rt/rtl8852be 还在为Linux系统无法识别RTL8852BE Wi-Fi 6网卡而烦恼吗?&#x1f…

2026/7/13 0:00:24

广氟 PTFE 高速线缆膜 —— 高端线缆绝缘材料新选择

PTFE高速线缆膜的基本概念与特点 PTFE 高速线缆膜是以聚四氟乙烯树脂为原料,经膨化双向拉伸制成的多孔绝缘薄膜,作为高速高频通信线缆的核心介质材料,内部形成均匀连通的微孔结构,兼具极低介电常数与介电损耗,能有效降…

2026/7/12 11:21:32

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…