深入理解 Java 中四種創建對象的方式

作者:六尺帳篷
鏈接:https://www.jianshu.com/p/7584b028cbda

調用 new 語句創建對象

// 使用java語言的關鍵字 new 創建對象,初始化對象數據 
    MyObject mo = new MyObject() ;

調用對象的 clone() 方法

MyObject anotherObject = new MyObject();
MyObject object = anotherObject.clone();

使用 clone() 方法克隆一個對象的步驟:

  1. 被克隆的類要實現 Cloneable 接口。
  2. 被克隆的類要重寫 clone()方法。

原型模式主要用於對象的複製,實現一個接口(實現 Cloneable 接口),重寫一個方法(重寫 Object 類中的 clone 方法),即完成了原型模式。

原型模式中的拷貝分爲 "淺拷貝" 和 "深拷貝":

(Object 類的 clone 方法只會拷貝對象中的基本數據類型的值,對於數組、容器對象、引用對象等都不會拷貝,這就是淺拷貝。如果要實現深拷貝,必須將原型模式中的數組、容器對象、引用對象等另行拷貝。)

原型模式的優點。

原型模式的使用場景。

因爲以上優點,所以在需要重複地創建相似對象時可以考慮使用原型模式。

比如需要在一個循環體內創建對象,假如對象創建過程比較複雜或者循環次數很多的話,使用原型模式不但可以簡化創建過程,而且可以使系統的整體性能提高很多。

運用反射手段創建對象

我們先介紹一下反射:

反射的定義

哪裏用到反射機制?

jdbc 中有一行代碼:
Class.forName('com.mysql.jdbc.Driver.class');// 加載 MySql 的驅動類。 這就
是反射, 現在很多框架都用到反射機制, hibernate, struts 都是用反射機制實
現的。

反射的實現方式

在 Java 中實現反射最重要的一步, 也是第一步就是獲取 Class 對象, 得到 Class 對象後可以通過該對象調用相應的方法來獲取該類中的屬性、方法以及調用該類中的方法。

有 4 種方法可以得到 Class 對象:

實現 Java 反射的類

注意:Class 類是 Java 反射中最重要的一個功能類,所有獲取對象的信息 (包
括: 方法 / 屬性 / 構造方法 / 訪問權限) 都需要它來實現。

反射機制的優缺點

優點:

缺點:

運用反序列化手段

序列化與反序列化

Java 序列化是指把 Java 對象轉換爲字節序列的過程;而 Java 反序列化是指把字節序列恢復爲 Java 對象的過程。

爲什麼需要序列化與反序列化

我們知道,當兩個進程進行遠程通信時,可以相互發送各種類型的數據,包括文本、圖片、音頻、視頻等, 而這些數據都會以二進制序列的形式在網絡上傳送。那麼當兩個 Java 進程進行通信時,能否實現進程間的對象傳送呢?答案是可以的。如何做到呢?這就需要 Java 序列化與反序列化了。換句話說,一方面,發送方需要把這個 Java 對象轉換爲字節序列,然後在網絡上傳送;另一方面,接收方需要從字節序列中恢復出 Java 對象。基本原理和網絡通信是一致的,通過特殊的編碼方式:寫入數據將對象以及其內部數據編碼,存在在數組或者文件裏面然後發送到目的地後,在進行解碼,讀出數據。OK 到此顯示出來爲我們所用即可。

當我們明晰了爲什麼需要 Java 序列化和反序列化後,我們很自然地會想 Java 序列化的好處。其好處一是實現了數據的持久化,通過序列化可以把數據永久地保存到硬盤上(通常存放在文件裏),二是,利用序列化實現遠程通信,即在網絡上傳送對象的字節序列。

對象序列化

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/*
 * 序列化流:把對象按照流一樣的方式存入文本或者在網絡中傳輸;  對象 ---> 流 :ObjectOutputStream
 * 反序列化流:把文本文件中的流對象數據或者網絡中的流對象數據還原成對象。   流---> 對象 :ObjectInputStream
 */
public class ObjectStreamDemo {
    public static void main(String[] args) throws IOException {
        // 序列化數據其實就是把對象寫到文本文件
        //write();
        read();
    }

    private static void read() throws IOException {
        // 創建反序列化流對象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                "a.txt"));
        // 讀取,還原對象
        try {
            Person p = (Person) ois.readObject();
            System.out.println(p.toString());
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        ois.close();
    }

    private static void write() throws IOException {
        // 創建序列化流對象
        // public ObjectOutputStream(OutputStream out)
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
                "a.txt"));
        // 創建對象
        Person p = new Person("java", 20);
        oos.writeObject(p);
        // 釋放資源
        oos.close();
    }
}
import java.io.Serializable;

/*
 * NotSerializableException爲序列化異常,
 * 該類需要實現一個接口:Serializable序列化接口,該接口中並沒有任何方法,僅僅作爲標識。
 * 類似於此的沒有方法的接口是標記接口
 * 
 * !!!每一次去修改該類的時候都會生成一個新的序列化標識的值!,需要重新新,重新讀,這是基本方法。
 * 想辦法來固定該類的標識ID,人爲設定。這樣即使再次修改類的內容,只要ID固定了就可以保證,在讀取的時候一直是匹配的。
 * 增加 generated serial version ID,在類裏面直接點擊黃色即可,增加一個變化的ID值
 */

/*
 * 當有的成員變量不需要被序列化時:如何解決。
 * 方法使用transient關鍵字聲明不需要序列化的成員變量
 */
public class Person implements Serializable{

    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = -9164765814868887767L;

    private String name;
    private transient int age;

    public Person() {
        super();
    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person []";
    }

}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Kz6-YSP9EYjfk2MAHaexNQ