Java中创建对象的5种方式
作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象。然而这里有很多创建对象的方法,我们会在这篇文章中学到。
Java中有5种创建对象的方式,下面给出它们的例子还有它们的字节码
使用new关键字 | } → 调用了构造函数 |
使用Class类的newInstance方法 | } → 调用了构造函数 |
使用Constructor类的newInstance方法 | } → 调用了构造函数 |
使用clone方法 | } → 没有调用构造函数 |
使用反序列化 | } → 没有调用构造函数 |
如果你运行了末尾的的程序,你会发现方法1,2,3用构造函数创建对象,方法4,5没有调用构造函数。
1.使用new关键字
这是最常见也是最简单的创建对象的方式了。通过这种方式,我们可以调用任意的构造函数(无参的和带参数的)。
Employee emp1 = new Employee();
0: new #19 // class org/programming/mitra/exercises/Employee
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();
或者 Employee emp2 = Employee.class.newInstance();
51: invokevirtual #70 // Method java/lang/Class.newInstance:()Ljava/lang/Object;
3.使用Constructor类的newInstance方法
和Class类的newInstance方法很像, java.lang.reflect.Constructor类里也有一个newInstance方法可以创建对象。我们可以通过这个newInstance方法调用有参数的和私有的构造函数。
Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();
111: invokevirtual #80 // Method java/lang/reflect/Constructor.newInstance:([Ljava/lang/Object;)Ljava/lang/Object;
这两种newInstance方法就是大家所说的反射。事实上Class的newInstance方法内部调用Constructor的newInstance方法。这也是众多框架,如Spring、Hibernate、Struts等使用后者的原因。想了解这两个newInstance方法的区别,请看这篇Creating objects through Reflection in Java with Example.
4.使用clone方法
无论何时我们调用一个对象的clone方法,jvm就会创建一个新的对象,将前面对象的内容全部拷贝进去。用clone方法创建对象并不会调用任何构造函数。
要使用clone方法,我们需要先实现Cloneable接口并实现其定义的clone方法。
Employee emp4 = (Employee) emp3.clone();
162: invokevirtual #87 // Method org/programming/mitra/exercises/Employee.clone ()Ljava/lang/Object;
5.使用反序列化
当我们序列化和反序列化一个对象,jvm会给我们创建一个单独的对象。在反序列化时,jvm创建对象并不会调用任何构造函数。
为了反序列化一个对象,我们需要让我们的类实现Serializable接口
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();
261: invokevirtual #118 // Method java/io/ObjectInputStream.readObject:()Ljava/lang/Object;
我们从上面的字节码片段可以看到,除了第1个方法,其他4个方法全都转变为invokevirtual(创建对象的直接方法),第一个方法转变为两个调用,new和invokespecial(构造函数调用)。
例子
让我们看一看为下面这个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
Java中创建对象的5种方式的更多相关文章
- Java中创建对象的几种方式
Java中创建对象的五种方式: 作为java开发者,我们每天创建很多对象,但是我们通常使用依赖注入的方式管理系统,比如:Spring去创建对象,然而这里有很多创建对象的方法:使用New关键字.使用Cl ...
- Java中创建对象的五种方式
我们总是讨论没有对象就去new一个对象,创建对象的方式在我这里变成了根深蒂固的new方式创建,但是其实创建对象的方式还是有很多种的,不单单有new方式创建对象,还有使用反射机制创建对象,使用clone ...
- 【转】Java中创建对象的5种方式
Java中创建对象的5种方式 作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象.然而这里有很多创建对象的方法,我们会在这篇文章中学到. Java中有 ...
- Java中创建对象的5种方式 &&new关键字和newInstance()方法的区别
转载:http://www.kuqin.com/shuoit/20160719/352659.html 用最简单的描述来区分new关键字和newInstance()方法的区别:newInstance: ...
- Java技术——Java中创建对象的5种方式
此文为译文 原文连接:https://dzone.com/articles/5-different-ways-to-create-objects-in-java-with-ex 0. 前言 作为Jav ...
- Java 中创建对象的 5 种方式!
Java中有5种创建对象的方式,下面给出它们的例子还有它们的字节码 Employee类: class Employee implements Cloneable, Serializable { pri ...
- 第一弹:Java 中创建对象的4种方式
Java 是面向对象的语言,不可避免的,"对象"这个概念是 Java 语言的核心部分,这里来简单讨论一下在 Java 中创建一般对象的方法. 总结下来有以下4种创建对象的方法: 使 ...
- 第001弹:Java 中创建对象的4种方式
Java 是面向对象的语言,不可避免的,“对象”这个概念是 Java 语言的核心部分,这里来简单讨论一下在 Java 中创建一般对象的方法. 总结下来有以下4种创建对象的方法: 使用 new 关键字调 ...
- Java中创建对象的5种方法
将会列举5种方法去创建 Java 对象,以及他们如何与构造函数交互,并且会有介绍如何去使用这些方法的示例. 作为一个 Java 开发人员,我们每天都会创建大量的 Java 对象,但是我们通常会使用依赖 ...
随机推荐
- hello,world!
我是马燕,在2017即将来临之际,我希望自己,在新的一年里,能开开心心,健健康康,家人平平安安! 我会努力工作,努力学习,离自己的理想越来越接近. 以后我会将我的所学所得写在这里,供未来的自己随时查看 ...
- 深入浅出node(2) 模块机制
这部分主要总结深入浅出Node.js的第二章 一)CommonJs 1.1CommonJs模块定义 二)Node的模块实现 2.1模块分类 2.2 路径分析和文件定位 2.2.1 路径分析 2.2.2 ...
- Linux常用命令大全
系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIO ...
- 9.PNG的制作
1.背景自适应且不失真问题的存在 制作自适应背景图片是UI开发的一个广泛问题,也是界面设计师渴望解决的问题,我相信我们彼此都深有体会. 比如: 1.列表的背景图一定,但是列表的高度随着列表 ...
- Android版本和API Level对应关系
http://developer.android.com/guide/topics/manifest/uses-sdk-element.html Platform Version API ...
- 消费RabbitMQ时的注意事项,如何禁止大量的消息涌到Consumer
按照官网提供的订阅型写法( Retrieving Messages By Subscription ("push API")) 我发现,RabbitMQ服务器会在短时间内发送大量的 ...
- mysql 数据库引擎
一.数据库引擎 数据库引擎是用于存储.处理和保护数据的核心服务.利用数据库引擎可控制访问权限并快速处理事务,从而满足企业内大多数需要处理大量数据的应用程序的要求. 使用数据库引擎创建用于联机事务处理或 ...
- 无法安装Windows Live“OnCatalogResult:0x80190194”错误的解决方法
今天想安装一个博客客户端,结果安装一直报错"OnCatalogResult:0x80190194",百度查到了解决发放再此记录下来,以备后用. 到官网下载了一个在线安装程序,可是一 ...
- node 异步回调解决方法之yield
先看如何使用 使用的npm包为genny,npm 安装genny,使用 node -harmony 文件(-harmony 为使用es6属性启动参数) 启动项目 var genny= require( ...
- [转]ASP.NET Core 中的那些认证中间件及一些重要知识点
本文转自:http://www.qingruanit.net/c_all/article_6645.html 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系 ...