转自https://www.cnblogs.com/wxd0108/p/5685817.html

作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象。然而这里有很多创建对象的方法,我们会在这篇文章中学到。

Java中有5种创建对象的方式,下面给出它们的例子还有它们的字节码

使用new关键字 } → 调用了构造函数
使用Class类的newInstance方法 } → 调用了构造函数
使用Constructor类的newInstance方法 } → 调用了构造函数
使用clone方法 } → 没有调用构造函数
使用反序列化 } → 没有调用构造函数

如果你运行了末尾的的程序,你会发现方法1,2,3用构造函数创建对象,方法4,5没有调用构造函数。

1.使用new关键字

这是最常见也是最简单的创建对象的方式了。通过这种方式,我们可以调用任意的构造函数(无参的和带参数的)。

  1. Employee emp1 = new Employee();
  2. 0: new #19 // class org/programming/mitra/exercises/Employee
  3. 3: dup
  4. 4: invokespecial #21 // Method org/programming/mitra/exercises/Employee."":()V

2.使用Class类的newInstance方法

我们也可以使用Class类的newInstance方法创建对象。这个newInstance方法调用无参的构造函数创建对象。

我们可以通过下面方式调用newInstance方法创建对象:

  1. Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee").newInstance();
  2. 或者
  3.  
  4. Employee emp2 = Employee.class.newInstance();
  5. 51: invokevirtual #70 // Method java/lang/Class.newInstance:()Ljava/lang/Object;

3.使用Constructor类的newInstance方法

和Class类的newInstance方法很像, java.lang.reflect.Constructor类里也有一个newInstance方法可以创建对象。我们可以通过这个newInstance方法调用有参数的和私有的构造函数。

  1. Constructor<Employee> constructor = Employee.class.getConstructor();
  2. Employee emp3 = constructor.newInstance();
  3. 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方法。

  1. Employee emp4 = (Employee) emp3.clone();
  2. 162: invokevirtual #87 // Method org/programming/mitra/exercises/Employee.clone ()Ljava/lang/Object;

5.使用反序列化

当我们序列化和反序列化一个对象,jvm会给我们创建一个单独的对象。在反序列化时,jvm创建对象并不会调用任何构造函数。
为了反序列化一个对象,我们需要让我们的类实现Serializable接口

  1. ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
  2. Employee emp5 = (Employee) in.readObject();
  3. 261: invokevirtual #118 // Method java/io/ObjectInputStream.readObject:()Ljava/lang/Object;

我们从上面的字节码片段可以看到,除了第1个方法,其他4个方法全都转变为invokevirtual(创建对象的直接方法),第一个方法转变为两个调用,new和invokespecial(构造函数调用)。

例子

让我们看一看为下面这个Employee类创建对象:

  1. class Employee implements Cloneable, Serializable {
  2. private static final long serialVersionUID = 1L;
  3. private String name;
  4. public Employee() {
  5. System.out.println("Employee Constructor Called...");
  6. }
  7. public String getName() {
  8. return name;
  9. }
  10. public void setName(String name) {
  11. this.name = name;
  12. }
  13. @Override
  14. public int hashCode() {
  15. final int prime = 31;
  16. int result = 1;
  17. result = prime * result + ((name == null) ? 0 : name.hashCode());
  18. return result;
  19. }
  20. @Override
  21. public boolean equals(Object obj) {
  22. if (this == obj)
  23. return true;
  24. if (obj == null)
  25. return false;
  26. if (getClass() != obj.getClass())
  27. return false;
  28. Employee other = (Employee) obj;
  29. if (name == null) {
  30. if (other.name != null)
  31. return false;
  32. } else if (!name.equals(other.name))
  33. return false;
  34. return true;
  35. }
  36. @Override
  37. public String toString() {
  38. return "Employee [name=" + name + "]";
  39. }
  40. @Override
  41. public Object clone() {
  42. Object obj = null;
  43. try {
  44. obj = super.clone();
  45. } catch (CloneNotSupportedException e) {
  46. e.printStackTrace();
  47. }
  48. return obj;
  49. }
  50. }

下面的Java程序中,我们将用5种方式创建Employee对象。你可以从GitHub找到这些代码。

  1. public class ObjectCreation {
  2. public static void main(String... args) throws Exception {
  3. // By using new keyword
  4. Employee emp1 = new Employee();
  5. emp1.setName("Naresh");
  6. System.out.println(emp1 + ", hashcode : " + emp1.hashCode());
  7. // By using Class class's newInstance() method
  8. Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee")
  9. .newInstance();
  10. // Or we can simply do this
  11. // Employee emp2 = Employee.class.newInstance();
  12. emp2.setName("Rishi");
  13. System.out.println(emp2 + ", hashcode : " + emp2.hashCode());
  14. // By using Constructor class's newInstance() method
  15. Constructor<Employee> constructor = Employee.class.getConstructor();
  16. Employee emp3 = constructor.newInstance();
  17. emp3.setName("Yogesh");
  18. System.out.println(emp3 + ", hashcode : " + emp3.hashCode());
  19. // By using clone() method
  20. Employee emp4 = (Employee) emp3.clone();
  21. emp4.setName("Atul");
  22. System.out.println(emp4 + ", hashcode : " + emp4.hashCode());
  23. // By using Deserialization
  24. // Serialization
  25. ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.obj"));
  26. out.writeObject(emp4);
  27. out.close();
  28. //Deserialization
  29. ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
  30. Employee emp5 = (Employee) in.readObject();
  31. in.close();
  32. emp5.setName("Akash");
  33. System.out.println(emp5 + ", hashcode : " + emp5.hashCode());
  34. }
  35. }

程序会输出:

  1. Employee Constructor Called...
  2. Employee [name=Naresh], hashcode : -1968815046
  3. Employee Constructor Called...
  4. Employee [name=Rishi], hashcode : 78970652
  5. Employee Constructor Called...
  6. Employee [name=Yogesh], hashcode : -1641292792
  7. Employee [name=Atul], hashcode : 2051657
  8. Employee [name=Akash], hashcode : 63313419

Java 创建对象的几种方式的更多相关文章

  1. Java创建对象的4种方式?

     [Java创建对象的4种方式?] 1)通过new语句实例化一个对象 2)通过反射机制创建对象 3)通过clone()方法创建一个对象  (复制) 4)通过反序列化方式创建对象

  2. Java创建对象的几种方式

    解析:Java创建对象的几种方式(重要):(1) 用new语句创建对象,这是最常见的创建对象的方法.(2) 运用反射手段,调用java.lang.Class或者java.lang.reflect.Co ...

  3. &和&&的共同点和区别、Java字符含义和Java创建对象的几种方式

    一.&和&&的共同点和区别 1.&和&&的联系(共同点): &和&&都可以用作逻辑与运算符,但是要看使用时的具体条件来决定. 操 ...

  4. Java创建对象的几种方式。

    Java创建对象的几种方式(重要): (1) 用new语句创建对象,这是最常见的创建对象的方法. (2) 运用反射手段,调用java.lang.Class或者java.lang.reflect.Con ...

  5. 面试阿里,字节跳动,华为必须知道的Java创建对象的5种方式

    Java创建对象的5种方式 1.直接new,调用了构造器2.通过clone(),没有调用构造器3.通过反射,调用了构造器4.通过反序列化,没有调用构造器5.通过Unsafe类的allocateInst ...

  6. Java基础知识强化25:Java创建对象的四种方式

    1. Java程序中对象的创建有四种方式: ● 调用new语句创建对象,最常见的一种 ● 运用反射手段创建对象,调用java.lang.Class 或者 java.lang.reflect.Const ...

  7. Java创建对象的4种方式

    Java创建对象的方式共有四种: 使用new语句实例化一个对象: 通过反射机制创建对象: 通过clone()方法创建一个对象: 通过反序列化的方式创建对象. 一.使用new语句实例化一个对象 new语 ...

  8. 【Java基础】Java创建对象的五种方式

    Java中创建(实例化)对象的五种方式 1.用new语句直接创建对象,这是最常见的创建对象的方法. 2.通过工厂方法返回对象,如:String str = String.valueOf(23); 3. ...

  9. java创建对象的四种方式

    1.最常见的 new 一个 2使用反射机制创建对象,直接调用非构造函数 Class obj=Class.forName("A"); A a=obj.newInstance(); C ...

随机推荐

  1. oracle的存储过程和函数有什么区别?

    Oracle中的函数与存储过程的区别:      A:函数必须有返回值,而过程没有. B:函数可以单独执行.而过程必须通过execute执行. C:函数可以嵌入到SQL语句中执行.而过程不行. 其实我 ...

  2. [ cocos2d-JS ] 启动项目

    1, 打开windows命令行 2, cd 到项目的文件夹 3, 执行 cocos run -p web

  3. 4 —— node —— 启动一个 http 服务器

    const http = require('http'); const server = http.createServer(); // 绑定客户端请求事件 // on => 绑定事件 // r ...

  4. mariadb galera启动问题

    搭建了mariadb galera集群后,整个集群停掉后如何启动呢,我们要先启动那个节点呢,今天我尝试把集群机器全部停掉,然后任意启动一个节点,发现报如下的错误: 170620 21:32:55 [E ...

  5. Windows10 网络图标消失 连接不上网络 的解决方法

    [背景]电脑win10的,下载一个软件重启之后网络图标消失,并且无法联网. 参照此解决方法: 原因: [Windows Event Log]服务对应的注册表出现问题,导致无法正常启动,进而导致一些依赖 ...

  6. IPsec_crypto[6]次配置

    IPsec_crypto[6]次配置: ①.①:crypto isakmp enbale——启用ISAKMP ②.②:crypto isakmp policy 10——创建一个策略组 ③:encryp ...

  7. 061-PHP函数定义默认参数

    <?php function add($x=2,$y=3){ //定义函数并设置默认参数 return $x+$y; } echo add(); //不传入参数调用add函数add(2,3) e ...

  8. Golang modules包依赖管理工具

    初始化 执行go mod  init module-name,其中module-name为包名字,执行完后会生成go.mod文件,如下 module module-name go 1.13 包管理 使 ...

  9. CodeForces - 402B Trees in a Row (暴力)

    题意:给定n个数,要求修改其中最少的数,使得这n个数满足ai + 1 - ai = k. 分析: 暴力,1000*1000. 1.这n个数,就是一个首项为a1,公差为k的等差数列.k已知,如果确定了a ...

  10. windows Driver 查询指定键值

    NTSTATUS status; HANDLE hKey = NULL; OBJECT_ATTRIBUTES oa; UNICODE_STRING strPath = RTL_CONSTANT_STR ...