Java中創建對象的5種方式

2022-01-22 尚學堂

譯文連結:http://www.codeceo.com/article/5-ways-java-create-object.html
英文原文:5 Different Ways to Create Objects in Java
孫騰浩

作為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/Employee3: dup4: 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等使用後者的原因。

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 : -1968815046Employee Constructor Called...Employee [name=Rishi], hashcode : 78970652Employee Constructor Called...Employee [name=Yogesh], hashcode : -1641292792Employee [name=Atul], hashcode : 2051657Employee [name=Akash], hashcode : 63313419


尚學堂:每天推送IT新技術文章,跟著我們擴展技術視野吧

即刻起關注尚學堂,發送「要課程」,

IT課程免費送!

相關焦點

  • 用Java創建對象的5種不同方式
    作為Java開發人員,我們通常每天創建許多對象,但是我們始終使用依賴管理系統(例如Spring)來創建這些對象。但是,還有更多創建對象的方法,我們將在本文中進行研究。用Java創建對象的共有五種方法,下面將通過示例說明這些方法,然後介紹創建對象的行的字節碼。
  • java創建對象的過程詳解(從內存角度分析)
    java對象的創建操作其實我在《JVM系列之類的加載機制》一文曾經提到過,包含兩個過程:類的初始化和實例化。為此為了理解的深入,我們還需要再來看一下類的生命周期。一張圖表示:從上面我們可以看到,對象的創建其實包含了初始化和使用兩個階段。有了這個印象之後,我們就能開始今天的文章了。
  • 五種方法創建java對象,你知道幾種呢?
    作為Java開發人員,我們通常每天都會創建許多對象,但是我們總是使用新的或依賴管理系統(例如Spring)來創建這些對象。但是,有更多方法可以創建本文中將要研究的對象。用Java創建對象的共有5種核心方式,下面將以其示例加以說明,然後介紹創建對象的行的字節碼。
  • 五種方法創建 Java 對象,你知道幾種呢?
    但是,有更多方法可以創建本文中將要研究的對象。用Java創建對象的共有5種核心方式,下面將以其示例加以說明,然後介紹創建對象的行的字節碼。但是,有很多API可以為我們創建對象,但是這些API還將間接使用這5種核心方式之一,例如Spring BeanFactory。如果您將執行最後給出的程序,則會看到方法1、2、3使用構造函數創建對象,而4、5沒有調用構造函數創建對象。
  • js創建對象的5種方式
    首先說說面向對象編程的特點:抽象:抓住核心問題封裝:只能通過對象來訪問方法繼承:從已有的對象下繼承出新的對象多態:多對象的不同形態創建對象的5種方式javascript 創建對象簡單的來說,無非就是使用內置對象或各種自定義對象,當然還可以使用JSON,但寫法有很多,也能混合使用。
  • Java之創建多線程的第一種方式,thread類
    在java.long包下,有這樣一個類java.long.Thread類代表線程,所有的線程對象必須是Thread類或其子類的實例。每一個線程的作用是完成一定的任務,就是執行一段程序流即一段順序執行的代碼。Java中使用線程執行體來代表這段程序流。
  • java的線程創建方式
    Thread類java語言中的Thread類是一個基本的線程類,用於創建線程、中斷線程、獲取線程的基本信息、運行狀態等。我們首先了解下利用Thread類創建線程實例的二種方式。().getName()); }}//創建線程實例Thread thread = new MyThread();//啟動線程thread.start();實現Runable接口創建線程//實現runnable接口創建任務類class MyTask implements Runnable{//重寫run方法創建工作任務 public void run() {
  • 如何在javascript中創建一個對象?
    javascript是一門基於對象而不是面向對象的語言,由於它的這個缺陷,在javascript中實現面向對象時十分彆扭,就比如創建對象,由於在ES6之前沒有class關鍵字,想要創建對象必須依賴以下幾種間接方式。
  • EffectiveJava-1-創建和銷毀對象
    可以不用在每次調用時都創建一個新的對象,可以使用預先構建好的對象,或將構建好的對象緩存起來,進行重複利用,適用於經常請求創建相同對象,並且創建對象的代價很高,如常見的單例模式寫法就是對這一點的應用;實例受控的類:能為重複的調用返回相同的類,有助於類控制某個時刻哪些實例應該存在,功能如下:1.確保它是一個Singleton或者是不可實例化的;2.使得不可變的類不會存在兩個相等的實例
  • 對象的創建過程
    我們使用main函數創建School的一個對象,那麼這個過程發生了哪些事情?在JVM內存中多了什麼呢?讓我們一起看下吧!,大致可以分為以下5步:在詳細了解這5個步驟之前我們再詳細聊一下對象頭,在synchronized鎖升級過程分析的時候我們已經初步接觸過它。
  • js創建對象的幾種方式
    使用Object構造函數來創建一個對象,下面代碼創建了一個person對象,並用兩種方式列印出了Name的屬性值。person["5"],這裡是合法的;另外使用這種加括號的方式欄位之間是可以有空格的如person["my age"].
  • Java 生成隨機數的 5 種方式,你知道幾種?
    方法是 的,因此在多線程情況下,只有一個線程會負責創建偽隨機數生成器(使用當前時間作為種子),其他線程則利用該偽隨機數生成器產生隨機數。Java生成隨機數的幾種高級用法,這篇推薦看一下。 因此 方法是線程安全的。
  • 如何應用GOF設計模式中的構建者模式創建複合對象實例
    軟體項目實訓及課程設計指導——如何應用GOF設計模式中的構建者模式創建複合對象實例1、GOF設計模式中的構建者模式構建者設計模式能夠將一個複雜對象(它一般為組合類)的構建過程與它的表示部件相互分離,使得同樣的構建過程可以創建出不同的表示部件——也就是希望所獲得的目標組合對象
  • 每日一課 | 從Java中的文件讀取對象
    在此示例中,您將學習如何從保存的文件中讀取對象或如何反序列化序列化的文件
  • 關於 Java 對象序列化您不知道的 5 件事
    因此,我們需要 serialVersionUID 欄位,它是通過對原始(或 V1)版本的 Person 類運行 JDK serialver命令計算出的。實際上,只需將二進位序列化流的內容轉儲到控制臺,就足以看清類是什麼樣子,以及它包含什麼內容。這對於安全性有著不良影響。例如,當通過 RMI 進行遠程方法調用時,通過連接發送的對象中的任何 private 欄位幾乎都是以明文的方式出現在套接字流中,這顯然容易招致哪怕最簡單的安全問題。幸運的是,序列化允許 「hook」 序列化過程,並在序列化之前和反序列化之後保護(或模糊化)欄位數據。
  • Java Web安全 || Java基礎 · Java IO/NIO多種讀寫文件方式
    // 創建二進位輸出流對象 ByteArrayOutputStream out = new ByteArrayOutputStream(); // 循環讀取文件內容 while ((a = fis.read(bytes)) !
  • JavaScript OOP 創建對象的7種方式
    ,但卻沒有解決方法共享的問題,方法依然在每個對象裡創建了一遍 。在第4行的代碼中我定義了Dog構造方法,這讓Dog的原型對象的 constructor 屬性指向了Dog。5-7行代碼又為Dog的原型對象添加了2個屬性和一個方法。
  • 「JAVA」屬性、路徑分隔符有何不同?file對象創建,文件過濾器
    文件02創建File對象Java的I/O操作和通信的相關類和接口位於java.io包中,包中有提供大量的File類是在I/O包中既可以表示磁碟文件,又可以表示磁碟目錄的對象的路徑。該類包含了創建文件、刪除文件、重命名文件,判斷文件讀寫權限、判斷文件是否存在等功能方法;但需要注意的是File類中的api只能設置和獲取文件本身的信息(名稱、文件大小、文件類型),不能設置和獲取文件的內容。
  • 如何用 Map 對象創建 Set 對象
    Map會更加高效一些,這種遍歷方式的時間複雜度是O(n)。java.util包中有很多Map類,其中一些Map類有著對應類型的Set類實現,例如TreeMap和HashMap。這些Set類都是基於對應的Map類實現的,因此它們和對應的Map類保持相同的算法複雜度以及並發特性。本文的重點來了。我在完成並發專修課程中的某道練習題時,需要一個快速高效並且線程安全的HashSet。
  • Java 數組中new Object[5]語句是否創建了5個對象?
    點擊關注公眾號,Java乾貨及時送達作者:王俊凱夫人來源:blog.csdn.net/qq_33642117/article/details/52214403Java 數組的本質是一個Java類,它是通過new語句來實例化,但是這個new語句卻不會實例化數組中的對象