首頁  >  文章  >  Java  >  Java中如何避免不必要的物件創建?

Java中如何避免不必要的物件創建?

PHPz
PHPz轉載
2023-04-24 22:31:051499瀏覽

簡介

在Java開發中,程式設計師要盡可能的避免創建相同的功能的對象,因為這樣既消耗內存,又影響程式運行速度。在這種情況下可以考慮重複利用物件。

接下來舉例幾種物件重複利用的場景,看看我們是不是有中招了,如果有趕緊趁著還沒被發現悄悄改掉,被發現了會被diss啦!

1、String和Boolean

如下兩種寫法看似沒有什麼差別,但是如果深入jvm底層了解,我們可以利用jvm運行時常數池的特性,避免創建具有相同功能的String物件(尤其是在循環內部創建)可以帶來比較可觀的效能優化以及節省記憶體。

錯誤寫法

// 每次都会创建一个新的String对象,且不会加入常量池
String name2 = new String("李子捌");

正確寫法

// 正确写法
String name1 = "李子捌";

除此之外,剛寫Java程式碼的程式設計師們,也要正確的選擇String、StringBuilder、StringBuffer類別的使用。 String為不可變對象,通常用於定義不變字串;StringBuilder、StringBuffer用於可變字串操作場景,如字串拼接;其中StringBuffer是執行緒安全的,它透過Synchronized關鍵字來實現執行緒同步。

// StringBuffer中的append()方法
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

// StringBuilder中的append()方法
public StringBuilder append(String str) {
    super.append(str);
    return this;
}

Boolean是常用的類型,在開發中也應該使用Boolean.valueof()而不是new Boolean(),從Boolean的源碼可以看出,Boolean類別定義了兩個final static的屬性,而Boolean.valueof()直接回傳的是定義的這兩個屬性,而new Boolean()卻會建立新的物件。

public static final Boolean TRUE = new Boolean(true);

public static final Boolean FALSE = new Boolean(false);

2、自動拆箱和裝箱

Java提供了基本資料類型的自動拆箱和裝箱功能,那是不是意味著我們可以在程式碼中隨意的使用這兩種呢?其實理論上在程式碼層面是沒得問題,不過在具體的效能方面還是有優化的空間啦! ! !

我們來測試下效能

long start = System.currentTimeMillis();
Integer sum = 0;
for (int i = 0; i < 100000; i++) {
    sum += i;
}
System.out.println(System.currentTimeMillis() - start);

使用Integer耗時3毫秒

Java中如何避免不必要的物件創建?

long start = System.currentTimeMillis();
// 修改Integer 为 int 
int sum = 0;
for (int i = 0; i < 100000; i++) {
    sum += i;
}
System.out.println(System.currentTimeMillis() - start);

使用int耗時0毫秒

Java中如何避免不必要的物件創建?

#因此關於自動拆箱裝箱的使用,我們其實也可以做適當的考慮,畢竟有時候程式碼效能就是一點點擠出來的嘛! ! !

3、正規表示式

正規表示式我們常用於字串是否合法的校驗,我們先來看一段簡單的程式碼(大家有沒有一眼看出問題呢?我想你肯定看出來了!!!):

public static void main(String[] args) {

    String email = "1057301174@qq.com";
    String regex = "^([a-z0-9A-Z]+[-|\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-zA-Z]{2,}$";

    long start = System.currentTimeMillis();
    for (int i = 0; i < 10000; i++) {
        email.matches(regex);
    }

    System.out.println(System.currentTimeMillis() - start);

}

執行這段程式碼的時間,一共耗時71毫秒,看似好像挺快的!

Java中如何避免不必要的物件創建?

但我們做個非常簡單的優化,優化後的程式碼如下:

public static void main(String[] args) {

    String email = "1057301174@qq.com";
    String regex = "^([a-z0-9A-Z]+[-|\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-zA-Z]{2,}$";
    Pattern pattern = Pattern.compile(regex);

    long start = System.currentTimeMillis();
    for (int i = 0; i < 10000; i++) {
        //email.matches(regex);
        pattern.matcher(email);
    }

    System.out.println(System.currentTimeMillis() - start);

}

再次執行程式碼,一共耗時1毫秒,快了70倍呀! ! !

Java中如何避免不必要的物件創建?

這是因為String.matches()方法在循環中建立時,每次都需要執行Pattern.compile(regex),而建立Patter實例的成本很高,因為需要將正規表示式編譯成有限狀態機( finite state machine)。這種我們常常會因為Java api提供了比較方便的方法呼叫而忽略了效能考究,往往不容易被發現。

以上是Java中如何避免不必要的物件創建?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除