Java中创建对象的5种方式

作为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创建对象的方式共有四种: 使用new语句实例化一个对象: 通过反射机制创建对象: 通过clone()方法创建一个对象: 通过反序列化的方式创建对象. 一.使用new语句实例化一个对象 new语 ...

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

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

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

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

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

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

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

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

  6. java中创建对象的方式

    Java中有5种创建对象的方式,下面给出它们的例子还有它们的字节码 使用new关键字 } → 调用了构造函数 使用Class类的newInstance方法 } → 调用了构造函数 使用Construc ...

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

    转自https://www.cnblogs.com/wxd0108/p/5685817.html 作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象.然而 ...

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

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

  9. Java创建对象的几种方法

    有时候,也可能碰到这样面试题,如: Java创建对象有哪几种方法? 除了new之外,java创建对象还有哪几种方式? 本文结合例子,给出几种Java创建对象的方法,Here we go~~~~ 使用n ...

随机推荐

  1. Efficient store queue architecture

    One embodiment of the present invention provides a store queue that applies the stores to a memory s ...

  2. VxWorks启动过程的详细解释(上)

    vxworks有三个图像: VxWorks Image有三种类型的文件 Loadable Images:由Boot-ROM引导通过网口或串口下载到RAM ROM-based Images(压缩/没有压 ...

  3. GameBuilder见缝插针游戏开发系列(AA)

    今天推出了一款游戏叫<AA>.在最近IOS只是弹出一个游戏.非常心脏的孩子,但有很多乐趣.今天,我们谈论它tangide(GameBuilderV2.0)用控件UICanvas实现它. 在 ...

  4. WPF自定义控件 使用阿里巴巴图标

    原文:WPF自定义控件 使用阿里巴巴图标 上一篇介绍了 WPF自定义控件 按钮 的初步使用,在进一步介绍WPF自定义控件 按钮之前,先介绍一下如何在WPF项目中使用阿里巴巴图标,方便以后做示例. 1. ...

  5. Ubuntu 15.04 clang++ 3.6 编译boost 1.59/1.55

    Ubuntu 15.04已经可以直接通过apt-get insall 安装clang 3.6, 并且预装的gcc版本是4.9.2.这些安装过程在这里介绍. 首先下载boost源码 wget -O bo ...

  6. WPF特效-实现3D足球效果

    原文:WPF特效-实现3D足球效果 WPF 实现 3D足球效果,效果图如下:  每个面加载不同贴图. <UserControl x:Class="MediaBalll.Model3Ds ...

  7. 去掉 Windows 中控件的虚线框(当当 element == QStyle::PE_FrameFocusRect 时,直接返回,不绘制虚线框)

    在 Windows 中,控件得到焦点的时候,会显示一个虚线框,很多时候觉得不好看,通过自定义 QProxyStyle 就可以把这个虚线框去掉. 1 2 3 4 5 6 7 8 9 10 11 12 1 ...

  8. jquery trim()的用法

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  9. 一个由单例模式在多线程环境下引发的 bug

    问题症状 HTTP 日志系统,老是出现日志信息覆盖的情况.比如同时调用 A 接口和 B 接口,B 接口请求响应信息变成了 A 接口请求响应相关信息.这个问题在并发量大的情况下越来越严重. 问题初步分析 ...

  10. QTextStream 居然接受FILE*这样的传统参数

    实在是太爽.太牛了,无话可说-