实例对象的创建,我详细小伙伴们一定熟悉得不能再熟悉了,那你知道 Java 中创建对象到底有多少种方法吗?这里大明哥将介绍 6 中方式来创建一个 Java 对象:
- 使用
new
关键字 - 使用 Class 类的
newInstance()
- 使用
clone()
方法 - 使用 Constructor 类的
newInstance()
- 使用对象的反序列化
- 使用 ObjectFactory 或其他工厂方法
使用 new 关键字
这是最常见也是最简单的创建对象的方式,当使用 new
关键字时,Java 为对象分配内存,并调用类的构造函数初始化对象。
User user = new User("大明哥",18);
这种方式是我们大多数标准对象创建的方式。
使用 Class 类的newInstance()
每个类都是 Class
类的实例,我们可以通过 Class 对象的 newInstance()
来创建类的实例,这通常是通过反射来实现的。
User user = User.class.newInstance();
需要注意的是Class类的newInstance()
使用的是类的public 的无参构造器,也就是说如果我们创建的对象没有无参构造器,则会报如下错误:
Exception in thread "main" java.lang.InstantiationException: com.xxxx.User
at java.base/java.lang.Class.newInstance(Class.java:719)
at com.xxxx.feature.MainTest.main(MainTest.java:5)
Caused by: java.lang.NoSuchMethodException: com.xxxx.User.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3761)
at java.base/java.lang.Class.newInstance(Class.java:706)
... 1 more
当我们需要在运行时动态地创建对象,且只知道类名时,这种方式非常有用。但要注意,它只能调用无参构造函数。还有需要注意的是,该方法是 Java 9 后被标注为过时了。
使用 clone() 方法
如果一个类实现了 Cloneable
接口,那么它可以通过调用对象的 clone()
方法来创建一个新的对象副本。要使用 clone()
我们必须先实现Cloneable接口并复写Object的****clone()
。
public class User implements Cloneable{
private String name;
private Integer age;
@Override
public User clone() throws CloneNotSupportedException {
return (User) super.clone();
}
}
使用 clone()
克隆一个对象:
User user1 = new User("大明哥",18);
User user2 = user1.clone();
System.out.println("user1="+user1);
System.out.println("user2="+user2);
System.out.println(user1 == user2);
执行结果:
user1=User(name=大明哥, age=18)
user2=User(name=大明哥, age=18)
false
完成了内容的克隆,而且我们发现 user2 是一个全新的对象。
使用 Constructor 类的 newInstance()
这种方式同样是一种反射机制。可以通过获取类的 Constructor
对象,然后调用其 newInstance()
方法来创建实例。这种方式与Class类的newInstance()
方法很像,但是比它强大多了:
- 构造函数不再必须是无参的
- 构造函数不再必须是 public
我们 User 对象如下:
public class User{
private String name;
private Integer age;
// private 的无参构造函数
private User(){
this.name = "大明哥1号";
this.age = 35;
}
// public 的有参构造函数
public User(String name,Integer age) {
this.name = name;
this.age = age;
}
}
验证
public static void main(String[] args) throws Exception {
// 返回 public 和非public 的构造函数,也包括 private 的
Constructor<?>[] declaredConstructors = User.class.getDeclaredConstructors();
// 只返回 public 的构造函数
Constructor<?>[] constructors = User.class.getConstructors();
Constructor<?> noArgsConstructor = declaredConstructors[0];
Constructor<?> haveArgsConstructor = declaredConstructors[1];
noArgsConstructor.setAccessible(true); // 非public的构造必须设置true才能用于创建实例
Object user1 = noArgsConstructor.newInstance();
Object user2 = declaredConstructors[1].newInstance("大明哥", 18);
System.out.println(user1);
System.out.println(user2);
}
运行结果:
User(name=大明哥1号, age=35)
User(name=大明哥, age=18)
使用对象的反序列化
对象在序列化过程中被写入一个流中,之后可以从该流中反序列化来创建对象。在这个过程中,并不调用任何构造函数。
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
User user = (User) in.readObject();
关于 Java 序列化文章,大明哥用了四篇文章详细阐述了 Java 的序列化:
使用 ObjectFactory 或其他工厂方法
工厂方法是一种创建对象的设计模式,它使用一个专门的工厂类来创建对象实例。
User user = UserFactory.createUser();
这种方法在需要对对象创建进行更细粒度控制的场景中非常有用,例如实现依赖注入或在创建对象时应用某些特定的配置。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。