Java中创建对象的5种方法
将会列举5种方法去创建 Java 对象,以及他们如何与构造函数交互,并且会有介绍如何去使用这些方法的示例。
作为一个 Java 开发人员,我们每天都会创建大量的 Java 对象,但是我们通常会使用依赖管理系统去创建这些对象,例如 Spring 。然而,我们可以有更多的方式去创建对象,让我们一起在文章中去学习这些方法吧。
这里列举在 Java 中创建对象的五种方式,下面将介绍它们的示例,以及创建对象的行的字节码。
| 使用 new 关键字 | 构造函数会被调用 |
| 使用 Class 类的 newInstance() | 构造函数会被调用 |
| 使用 Constructor 类的 newInstance() | 构造函数会被调用 |
| 使用 clone() 方法 | 无构造函数调用 |
| 使用 deserialization | 无构造函数调用 |
如果最后执行给定的程序,您将看到方法1、2、3使用构造函数创建对象,而4、5不调用构造函数创建对象。
1.使用 new 关键字
这是创建一个对象最通用、常规的方法,同时也是最简单的方式。通过使用此方法,我们可以调用任何要调用的构造函数(默认使用无参构造函数)。
| 1 | Employee |
| 1 2 3 | 0:new #19 // class org/programming/mitra/exercises/Employe 3:dup 4: invokespecial #21 // Method org/programming/mitra/exercises/Employee."": ()V |
2.使用 Class 类的 newInstance()
我们能够使用 Class 类的 newInstance() 方法创建对象。这个 newInstance() 方法将调用无参构造方法去创建一个对象。
在下述代码中,我们通过调用 newInstance() 去创建一个对象:
Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee").newInstance();
或者:
| 1 | Employee emp2 = Employee.class.newInstance(); |
| 1 | 51: invokevirtual #70 // Method java/lang/Class.newInstance:()Ljava/lang/Object; |
3.使用 Constructor 类的 newInstance()
与 Class 类中的 newInstance() 方法相似,在此我们将使用 java.lang.reflect.Constructor 类中的 newInstance() 方法创建对象。通过使用这个 newInstance() 方法我们能够调用有参构造函数和私有构造函数。
| 1 2 | Constructor constructor = Employee.class.getConstructor(); Employee emp3 = constructor.newInstance(); |
| 1 | 111: invokevirtual #80 // Method java/lang/reflect/Constructor.newInstance:([Ljava/lang/Object;)Ljava/lang/Object; |
这两个 newInstance() 方法都被称为创建对象的反射方法。实际上, Class 类的 newInstance() 方法内部使用 Constructor 类的 newInstance() 方法。这就是为什么后者更受欢迎,并且也被 Spring、Hibernate、Structs 等不同的框架所使用的原因。更多关于上述两个 newInstance() 方法的区别请阅读 Creating objects through Reflection in Java with Example。
4.使用 Clone() 方法
每当我们对任何对象调用 clone() 时,jvm 都会为我们创建一个新对象,并将前一个对象的所有内容复制到其中。使用 clone 方法创建对象不会调用任何构造函数。
要在对象上使用 clone() 方法,我们需要实现 Cloneable 并在其中定义 clone() 方法。
| 1 | Employee emp4 = (Employee) emp3.clone(); |
| 1 | 162: invokevirtual #87 // Method org/programming/mitra/exercises/Employee.clone ()Ljava/lang/Object; |
Java 克隆是 Java 社区中最有争议的话题,它确实有它的缺点,但仍然是创建任何对象副本的最流行和最简单的方法,直到该对象完全填充 Java 克隆的强制条件。我在3篇长的[ Java Cloning Series ](https://programmingmitra.blogspot.in/search/label/Java Cloning)中详细介绍了克隆,其中包括(Java Cloning And Types Of Cloning (Shallow And Deep) In Details With Example,Java Cloning - Copy Constructor Versus Cloning,Java Cloning - Even Copy Constructors Are Not Sufficient),如果你想了解更多关于克隆的知识,请继续阅读它们。
5.使用 deserialization
每当我们序列化和反序列化对象时,JVM会为我们创建了一个独立的对象。在 deserialization 中,JVM 不使用任何构造函数来创建对象。
对于序列化对象,我们需要在类中实现 Serializable 接口。
| 1 2 | ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj")); Employee emp5 = (Employee) in.readObject(); |
| 1 | 261: invokevirtual #118 // Method java/io/ObjectInputStream.readObject:()Ljava/lang/Object; |
正如我们在上面的字节码片段中看到的,4个方法都被调用并转换为 invokevirtual(对象创建由这些方法直接处理),但第一个方法被转换为两个调用:一个是 new,另一个是 invokespecial(调用构造函数)。
在我的文章中,曾经讨论过序列化和反序列化的细节,如果你想了解更多相关知识,请继续阅读:Everything About Java Serialization Explained With Example。
示例
创建对象的 Employee 类:
class Employee implements Cloneable, Serializable
private static final long serialVersionUID = 1L;
private String name
public Employee() {
System.out.println("Employee Constructor Called...");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "Employee [name=" + name + "]";
}
@Override
public Object clone() {
Object obj = null;
try {
obj = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return obj;
}
}
在下面的 Java 程序中,我们将以5种方式创建 Employee 对象。您也可以在GitHub上找到源代码。
public class ObjectCreation {
public static void main(String... args) throws Exception {
// By using new keyword
Employee emp1 = new Employee();
emp1.setName("Naresh");
System.out.println(emp1 + ", hashcode : " + emp1.hashCode());
// By using Class class's newInstance() method
Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee")
.newInstance();
// Or we can simply do this
// Employee emp2 = Employee.class.newInstance();
emp2.setName("Rishi");
System.out.println(emp2 + ", hashcode : " + emp2.hashCode());
// By using Constructor class's newInstance() method
Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();
emp3.setName("Yogesh");
System.out.println(emp3 + ", hashcode : " + emp3.hashCode());
// By using clone() method
Employee emp4 = (Employee) emp3.clone();
emp4.setName("Atul");
System.out.println(emp4 + ", hashcode : " + emp4.hashCode());
// By using Deserialization
// Serialization
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.obj"));
out.writeObject(emp4);
out.close();
//Deserialization
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();
in.close();
emp5.setName("Akash");
System.out.println(emp5 + ", hashcode : " + emp5.hashCode());
}
}
此程序执行将有以下输出:
Employee Constructor Called...
Employee [name=Naresh], hashcode : -1968815046
Employee Constructor Called...
Employee [name=Rishi], hashcode : 78970652
Employee Constructor Called...
Employee [name=Yogesh], hashcode : -1641292792
Employee [name=Atul], hashcode : 2051657
Employee [name=Akash], hashcode : 63313419
原文:https://dzone.com/articles/5-different-ways-to-create-objects-in-java-with-ex
作者:Naresh Joshi
译者:陈苓洪
9月福利,关注公众号
后台回复:004,领取8月翻译集锦!
往期福利回复:001,002, 003即可领取!

Java中创建对象的5种方法的更多相关文章
- java中需要关注的3大方面内容/Java中创建对象的几种方法:
1)垃圾回收 2)内存管理 3)性能优化 Java中创建对象的几种方法: 1)使用new关键字,创建相应的对象 2)通过Class下面的new Instance创建相应的对象 3)使用I/O流读取相应 ...
- java中创建对象的五种方法
用最简单的描述来区分new关键字和newInstance()方法的区别:newInstance: 弱类型.低效率.只能调用无参构造.new: 强类型.相对高效.能调用任何public构造. newIn ...
- Java中创建对象的四种方法
第一种 使用new关键字 第二种 使用反射技术:1)通过Class类的newInstance()方法:2)通过Constructor类的newInstance方法 第三种 通过Object类的clon ...
- Java中创建对象的几种方式
Java中创建对象的五种方式: 作为java开发者,我们每天创建很多对象,但是我们通常使用依赖注入的方式管理系统,比如:Spring去创建对象,然而这里有很多创建对象的方法:使用New关键字.使用Cl ...
- Java中创建对象的五种方式
我们总是讨论没有对象就去new一个对象,创建对象的方式在我这里变成了根深蒂固的new方式创建,但是其实创建对象的方式还是有很多种的,不单单有new方式创建对象,还有使用反射机制创建对象,使用clone ...
- 【转】Java中创建对象的5种方式
Java中创建对象的5种方式 作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象.然而这里有很多创建对象的方法,我们会在这篇文章中学到. Java中有 ...
- 第一弹:Java 中创建对象的4种方式
Java 是面向对象的语言,不可避免的,"对象"这个概念是 Java 语言的核心部分,这里来简单讨论一下在 Java 中创建一般对象的方法. 总结下来有以下4种创建对象的方法: 使 ...
- 第001弹:Java 中创建对象的4种方式
Java 是面向对象的语言,不可避免的,“对象”这个概念是 Java 语言的核心部分,这里来简单讨论一下在 Java 中创建一般对象的方法. 总结下来有以下4种创建对象的方法: 使用 new 关键字调 ...
- Java中创建对象的5种方式 &&new关键字和newInstance()方法的区别
转载:http://www.kuqin.com/shuoit/20160719/352659.html 用最简单的描述来区分new关键字和newInstance()方法的区别:newInstance: ...
随机推荐
- Dubbo(一):Dubbo运行原理
前言: 在开始入门Javaweb时,学的基本都是MVC开发模式,一个项目基本上就是model,view,controller三层.但是随着系统的服务逐渐加多,SOA模式更加适合目前项目开发.而SOA模 ...
- mac下面有epoll?
没有的,但是mac下面有kqueue,跟epoll原理是差不多的. 这个是没办法的,如果实在需要,就用Ubuntu吧,这个也可以无缝迁移. 更多资源,更多文章由小白技术社提供(是我啦)
- mybatis 源码分析(五)Interceptor 详解
本篇博客将主要讲解 mybatis 插件的主要流程,其中主要包括动态代理和责任链的使用: 一.mybatis 拦截器主体结构 在编写 mybatis 插件的时候,首先要实现 Interceptor 接 ...
- jvm系列(六):Java服务GC参数调优案例
本文介绍了一次生产环境的JVM GC相关参数的调优过程,通过参数的调整避免了GC卡顿对JAVA服务成功率的影响. 这段时间在整理jvm系列的文章,无意中发现本文,作者思路清晰通过步步分析最终解决问题. ...
- Java基础之Comparable与Comparator
Java基础之Comparable与Comparator 一.前言: Java中实现对对象的排序一般情况下主要有以下两种实现方式(万物皆对象嘛): 对象所在的类实现Comparable 接口 定义比较 ...
- 如何理解JS中this指向的问题
首先,用一句话解释this,就是:指向执行当前函数的对象. 当前执行,理解一下,也就是说this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定.this到底指向谁?this的最终指向的 ...
- React项目升级遇到的问题复盘(2019-09-02)
老铁们,发没发现我换了个贼帅的头像,高端大气上档次,非洲大地我最凶!可把我自己牛逼坏了. 不扯啦不扯啦,抓紧进入今天的正题,从今天开始我会每天写一下每天工作的出现的问题,主要对这些问题出现的原因,以及 ...
- Java中指令重排
/** * 指令重排:代码执行顺序与预期不一致 (发生在前后行代码无联系时) * 目的:提高性能 * */ public class HappenBefore { private static int ...
- testlink+vertrigoServ搭建测试用例管理系统
1.testlink简介 Testlink是一个开源的基于web的测试用例管理系统,主要功能是测试用例的创建.管理和执行,并且提供了一些简单的统计功能. 目前的公司没有专用的测试用例管理系统,为了测试 ...
- atcoder E - Jigsaw(思维)
题目链接:http://agc017.contest.atcoder.jp/tasks/agc017_e 题解:这题很巧妙运用了cnt[i]抽象的表示了上下互补的状态,最后上面突出的一定要处理完.下面 ...