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

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

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

1.使用new关键字

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

  1. Employee emp1 = new Employee();
  1. 0: new #19 // class org/programming/mitra/exercises/Employee
  2. 3: dup
  3. 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();

或者

  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. Constructor<Employee> constructor = Employee.class.getConstructor();
  2. 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、Struts等使用后者的原因。

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;

5.使用反序列化

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

  1. ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
  2. Employee emp5 = (Employee) in.readObject();
  1. 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中5种创建对象的方法的更多相关文章

  1. C++中三种创建对象的方法【转】

    我们都知道C++中有三种创建对象的方法,如下: #include <iostream> using namespace std; class A { private: int n; pub ...

  2. Java中四种复制数组的方法

    JAVA语言的下面几种数组复制方法中,哪个效率最高? B.效率:System.arraycopy > clone > Arrays.copyOf > for循环 1.System.a ...

  3. JAVA 中两种判断输入的是否是数字的方法__正则化_

    JAVA 中两种判断输入的是否是数字的方法 package t0806; import java.io.*; import java.util.regex.*; public class zhengz ...

  4. Java中几种常用数据类型之间转换的方法

    Java中几种常用的数据类型之间转换方法: 1. short-->int 转换 exp: short shortvar=0; int intvar=0; shortvar= (short) in ...

  5. Java中四种引用:强、软、弱、虚引用

    这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...

  6. Java基础-Java中23种设计模式之常用的设计模式

    Java基础-Java中23种设计模式之常用的设计模式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.设计模式分类 设计模式是针对特定场景给出的专家级的解决方案.总的来说设 ...

  7. Java中23种经典设计模式详解

    Java中23种设计模式目录1. 设计模式 31.1 创建型模式 41.1.1 工厂方法 41.1.2 抽象工厂 61.1.3 建造者模式 101.1.4 单态模式 131.1.5 原型模式 151. ...

  8. Java中是构造器创建对象吗?

    首先,这里说明” Java中是构造器创建对象 “这句话是完全错误的. Java中构造器的作用主要是为了初始化变量的值...其实在执行构造器之前,Java对象所需要的内存空间,已经产生了... 一般可以 ...

  9. Java中的equals和hashCode方法

    本文转载自:Java中的equals和hashCode方法详解 Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要 ...

随机推荐

  1. Ubuntu 16.04安装Kate文本编辑工具

    Kate支持很多语言,比如NASM,比SBL3低那么一点,但是比Gedit好. 安装: sudo apt-get install kate 启动: 额外配置: 1.安装Kwrite sudo apt- ...

  2. Linux系统命令及文件的浏览、管理和维护

    在linux中什么是一个文件的路径呢,说白了就是这个文件存在的地方,例如在上一章提到的/root/.ssh/authorized_keys 这就是一个文件的路径.如果你告诉系统这个文件的路径,那么系统 ...

  3. Java Servlet DAO实践(二)

    Java Servlet DAO实践(二) DAO连接类 package com.seller.servlets.dao; import java.sql.*; public class DataBa ...

  4. (转) 淘淘商城系列——Redis五种数据类型介绍

    http://blog.csdn.net/yerenyuan_pku/article/details/72855562 Redis支持五种数据类型:string(字符串),hash(哈希),list( ...

  5. Java基础(三)--final关键字

    final通常是指"不可改变的",例如我们使用的常量 通常可以有三种使用情况: 一.final修饰数据 如果final修饰数据,也就是通常所说的常量,从字面上看,常量就是不能修改的 ...

  6. ThinkPHP---thinkphp会话支持和文件载入

    [一]会话控制 会话支持一般指cookie和session,在ThinkPHP里为了方便开发,封装了cookie和session方法. (1)session方法 在函数库封装了session方法 se ...

  7. ZOJ - 3981 - Balloon Robot (思维)

    参考自:https://blog.csdn.net/qq_36553623/article/details/78445558 题意: 第一行三个数字n, m, q表示有m个座位围成一个环,n个队伍,q ...

  8. Django基础——ORM字段和字段参数

    ORM概念: 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象( 1. 不同的程序员写的SQL水平参差不齐 2. ...

  9. [bzoj2141][排队] (分块大法好)

    Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的 ...

  10. log 框架 之间的关系

    日志框架分为两大部分 一部分是日志框架的抽象层,一部分是日志框架的具体实现 slf4j: 日志框架的抽象层 log4j,logback 日志框架的具体实现 如上图所示: slf4j的具体实现是:slf ...