1. 程式人生 > >雜談 論例項化類的第六種方式

雜談 論例項化類的第六種方式

你知道幾種例項化一個類的方式?

new?反射?還有呢?

*******************************************美麗的分割線*******************************

筆者總結了一下大概有以下六種方式:

(1)通過構造方法例項化一個類;

(2)通過Class例項化一個類;

(3)通過反射例項化一個類;

(4)通過克隆例項化一個類;

(5)通過反序列化例項化一個類;

(6)通過Unsafe例項化一個類;

Let us 直接上程式碼:

public class InstantialTest {

    private static Unsafe unsafe;
    static {
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            unsafe = (Unsafe) f.get(null);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) throws Exception {
        // 1. 構造方法
        User user1 = new User();
        // 2. Class,裡面實際也是反射
        User user2 = User.class.newInstance();
        // 3. 反射
        User user3 = User.class.getConstructor().newInstance();
        // 4. 克隆
        User user4 = (User) user1.clone();
        // 5. 反序列化
        User user5 = unserialize(user1);
        // 6. Unsafe
        User user6 = (User) unsafe.allocateInstance(User.class);

        System.out.println(user1.age);
        System.out.println(user2.age);
        System.out.println(user3.age);
        System.out.println(user4.age);
        System.out.println(user5.age);
        System.out.println(user6.age);
    }

    private static User unserialize(User user1) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D://object.txt"));
        oos.writeObject(user1);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D://object.txt"));
        // 反序列化
        User user5 = (User) ois.readObject();
        ois.close();
        return user5;
    }

    static class User implements Cloneable, Serializable {
        private int age = 20;

        public User() {
            this.age = 10;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
}

先不要急著往下看,你猜猜上面六種方式列印語句輸出各是多少?

不要看!

不要看!

不要看!

最後列印的結果是這樣:

10
10
10
10
10
0

意不意外?驚不驚喜?

最後一種通過Unsafe例項化的類,裡面的age的值竟然是0,而不是10或者20。

這是因為呼叫Unsafe的allocateInstance()方法只會給物件分配記憶體,並不會初始化物件中的屬性,所以int型別的預設值就是0。

還有其它方式例項化類嗎?歡迎補充!


歡迎關注我的公眾號“彤哥讀原始碼”,檢視更多原始碼系列文章, 與彤哥一起暢遊原始碼的海洋。

相關推薦

雜談 例項方式

你知道幾種例項化一個類的方式? new?反射?還有呢? *******************************************美麗的分割線******************************* 筆者總結了一下大概有以下六種方式: (1)通過構造方法例項化一個類; (2)通過Class例

雜談 實例方式

總結 pro img int clone null clas 分享圖片 err 你知道幾種實例化一個類的方式? new?反射?還有呢? 筆者總結了一下大概有以下六種方式: (1)通過構造方法實例化一個類; (2)通過Class實例化一個類; (3)通過反射實例化一個類; (

建立例項方式

今天在閱讀springboot原始碼時,發現建立物件不同於以往new關鍵字,Constructor建立,clone,反射呼叫以及反序列化的第六種寫法。 宣告 public class ApplicationConversionService extends FormattingC

Spring例項bean的三方式

概述 學習一下Spring IOC bean的三種例項化方式。 構造方法 靜態工廠方法 例項工廠方法 預設構造方法例項化bean 最常用的初始化bean方式 public class Person { private String name; pr

04--Spring例項Bean的三方式

上一小節已經新建了Gradle模組用來測試(如果沒有也沒關係,不影響接下來的分析,可以直接在Spring的spring-beans模組下測試即可)。接下來回顧一下Spring中的一些知識點,以便於更好的的分析原始碼,本小節分析一下Spring例項化bean的三種

spring例項bean的幾方式

1.使用類構造器實現例項化(bean的自身構造器)  1 <bean id = "orderService" class="cn.itcast.OrderServiceBean"/>  2.使用靜態工廠方法實現例項化 1 <bean id =

Spring例項Bean的三方式_例項工廠方法

第一步:Bean3實體 public class Bean3 { } 第二步:工廠 public class Bean3Factory { public Bean3 createBean3(){ return new Bean3();

Spring例項Bean的三方式及Bean的型別

1.使用類構造器例項化  [預設的類構造器] 1 <bean id=“orderService" class="cn.itcast.OrderServiceBean"/> 2.使用靜

spring中例項Bean的三方式

第一種方式:使用預設無參建構函式 在預設情況下: 它會根據預設無參建構函式來建立類物件。如果bean中沒有預設無參建構函式,將會建立失敗。 <bean id="c

java Class-載入的三方法 以及的初始方式 及終止執行的方式

1在命令列啟動虛擬機器jvm進行載入,2用class.forname()方法進行動態載入;3用ClassLoader.loadClass()進行動態載入;區別:用二方法載入時,還會對類進行解釋,執行其中的static語句塊;          用三方法時候,static語句塊

Asp.net 靜態思路實現

做頁面靜態化 網上經常提到的有兩種 1、模板頁+替換的方式 2、偽靜態化,地址重寫   現在我想採用第三種方式,基於網頁抓取技術實現(參考)   1、建立實現類 public class MyUri : System.Uri {

JVM規範中初始的5情況(有且僅有)

類從被載入到虛擬機器記憶體中開始,到卸載出記憶體為止,它的整個生命週期包括:載入、驗證、準備、解析、初始化、使用和解除安裝 7個階段。其中驗證、準備、解析3個部分統稱為連線。 載入、驗證、準備、初始化和解除安裝這5個階段的順序是確定的,類的載入過程必須按照這種順序按部就班的

建立java例項物件

建立java類並例項化類物件例一1.面向物件的程式設計關注於類的設計2.設計類實際上就是設計類的成員3.基本的類的成員,屬性(成員變數)&方法 面向物件思想的落地法則一:1.設計類,並設計類的成員(成員變數&成員方法)2.通過類,來建立類的物件(也稱作類的例項化) public cl

解釋C++例項的指標型別中的new

Intarray * parray = new Intarray();//括號 int * parray = new int(); 兩個都不止是申明,已經初始化了。 第一句是建立(例項化)了一個Intarrya的物件,指標parray指向它。 第二句是建立(分配了)了int型

python:例項物件時提示“TypeError: Employee() takes no arguments”的解決方法

最近開始學習python,學習面向物件的知識時遇到一個問題 在建立例項物件時提示“TypeError: Employee() takes no arguments”,百度翻譯了一下,意思是這個類的建構函式不接受引數 找了半天實在不理解哪裡出問題了,明明都在"_

C# 反射通過例項

在面向物件程式設計的時候,會遇到這樣的問題,一個父類有多個子類,需要建立一個父類的物件,再後面根據條件去把該物件例項化具體的某個子類,然後進行操作。當然用if else 或者switch來做也可以,但是後期擴充套件性不好,特別是要把這些類封裝成dll提供給被人用

php實現例項後自動進行錯誤以及異常處理(簡易版)

<?php class App { public function __construct() { /* * ini_set 設定配置項 * display_errors 是否在頁面顯示錯誤資訊 *

Java 多執行緒傳值有三方式,以及另方式

現在博主的需求是:有可能在同一個執行緒類執行不一樣的程式。上邊兩個紅框中的cron4j排程器使用的是一個,根據引數不同來執行的。如果我點選後邊的手動執行一次,按照我上邊給出的java程式碼是無法實現的。看下邊的新的程式碼: (adsbygoogle = window.adsbygoo

Delphi 通過字串例項

D2007 通過字串建立窗體類物件 1、需要在程式初始化的時候將類註冊,註冊到物件 RegGroups:(TRegGroups)中,以便查詢。 註冊類使用的函式:RegisterClass ,窗體初始化操作放在initialization 中。 un

例項,怎麼限制只能在堆或棧分配!

昨天一個同學去網易面試C++研發,問到了這麼一個問題:如何限制一個類物件只在棧(堆)上分配空間? 一般情況下,編寫一個類,是可以在棧或者堆分配空間。但有些時候,你想編寫一個只能在棧或者只能在堆上面分配空間的類。這能不能實現呢?仔細想想,其實也是可以滴。 在C