在Java中如何避免創(chuàng)建不必要的對(duì)象
簡(jiǎn)介
在Java開(kāi)發(fā)中,程序員要盡可能的避免創(chuàng)建相同的功能的對(duì)象,因?yàn)檫@樣既消耗內(nèi)存,又影響程序運(yùn)行速度。在這種情況下可以考慮重復(fù)利用對(duì)象。
接下來(lái)舉例幾種對(duì)象重復(fù)利用的場(chǎng)景,看看我們是不是有中招了,如果有趕緊趁著還沒(méi)被發(fā)現(xiàn)悄悄改掉,被發(fā)現(xiàn)了會(huì)被diss啦!
1、String和Boolean
如下兩種寫(xiě)法看似沒(méi)有什么區(qū)別,但是如果深入jvm底層了解,我們可以利用jvm運(yùn)行時(shí)常量池的特性,避免創(chuàng)建具有相同功能的String對(duì)象(尤其是在循環(huán)內(nèi)部創(chuàng)建)可以帶來(lái)比較可觀的性能優(yōu)化以及節(jié)約內(nèi)存。
錯(cuò)誤寫(xiě)法
// 每次都會(huì)創(chuàng)建一個(gè)新的String對(duì)象,且不會(huì)加入常量池
String name2 = new String("李子捌");
正確寫(xiě)法
// 正確寫(xiě)法 String name1 = "李子捌";
除此之外,剛寫(xiě)Java代碼的程序員們,也要正確的選擇String、StringBuilder、StringBuffer類的使用。String為不可變對(duì)象,通常用于定義不變字符串;StringBuilder、StringBuffer用于可變字符串操作場(chǎng)景,如字符串拼接;其中StringBuffer是線程安全的,它通過(guò)Synchronized關(guān)鍵字來(lái)實(shí)現(xiàn)線程同步。
// 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是常用的類型,在開(kāi)發(fā)中也應(yīng)該使用Boolean.valueof()而不是new Boolean(),從Boolean的源碼可以看出,Boolean類定義了兩個(gè)final static的屬性,而B(niǎo)oolean.valueof()直接返回的是定義的這兩個(gè)屬性,而new Boolean()卻會(huì)創(chuàng)建新的對(duì)象。
public static final Boolean TRUE = new Boolean(true); public static final Boolean FALSE = new Boolean(false);
2、自動(dòng)拆箱和裝箱
Java提供了基本數(shù)據(jù)類型的自動(dòng)拆箱和裝箱功能,那是不是意味著我們可以在代碼中隨意的使用這兩個(gè)類型呢?其實(shí)理論上在代碼層面是沒(méi)得問(wèn)題,不過(guò)在具體的性能方面還是有優(yōu)化的空間啦?。。?/p>
我們來(lái)測(cè)試下性能
long start = System.currentTimeMillis();
Integer sum = 0;
for (int i = 0; i < 100000; i++) {
sum += i;
}
System.out.println(System.currentTimeMillis() - start);
使用Integer耗時(shí)3毫秒

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耗時(shí)0毫秒

因此關(guān)于自動(dòng)拆箱裝箱的使用,我們其實(shí)也可以做適當(dāng)?shù)目紤],畢竟有時(shí)候代碼性能就是一點(diǎn)點(diǎn)擠出來(lái)的嘛?。。?/p>
3、正則表達(dá)式
正則表達(dá)式我們經(jīng)常用于字符串是否合法的校驗(yàn),我們先來(lái)看一段簡(jiǎn)單的代碼(大家有沒(méi)有一眼看出問(wèn)題呢?我想你肯定看出來(lái)了!?。。?/p>
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);
}
執(zhí)行這段代碼的時(shí)間,一共耗時(shí)71毫秒,看似好像挺快的!

但是我們做個(gè)非常簡(jiǎn)單的優(yōu)化,優(yōu)化后的代碼如下所示:
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);
}
再次執(zhí)行代碼,一共耗時(shí)1毫秒,快了70倍呀!??!

這是因?yàn)镾tring.matches()方法在循環(huán)中創(chuàng)建時(shí),每次都需要執(zhí)行Pattern.compile(regex),而創(chuàng)建Patter實(shí)例的成本很高,因?yàn)樾枰獙⒄齽t表達(dá)式編譯成一個(gè)有限狀態(tài)機(jī)( finite state machine)。這種我們經(jīng)常會(huì)因?yàn)镴ava api提供了比較方便的方法調(diào)用而忽略了性能考究,往往不容易被發(fā)現(xiàn)。這個(gè)時(shí)候就需要優(yōu)秀的你,去“咬文嚼字”啦!
總結(jié)
到此這篇關(guān)于在Java中如何避免創(chuàng)建不必要對(duì)象的文章就介紹到這了,更多相關(guān)Java避免創(chuàng)建不必要對(duì)象內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解自動(dòng)注冊(cè)Gateway網(wǎng)關(guān)路由配置
這篇文章主要為大家介紹了自動(dòng)注冊(cè)Gateway網(wǎng)關(guān)路由配置的方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
IDEA JeeSite框架httpSession.invalidate()無(wú)效問(wèn)題解決方案
這篇文章主要介紹了IDEA JeeSite框架httpSession.invalidate()無(wú)效問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
java通過(guò)證書(shū)訪問(wèn)etcd的實(shí)現(xiàn)步驟
Etcd提供了多種語(yǔ)言的客戶端庫(kù),本文主要介紹了java通過(guò)證書(shū)訪問(wèn)etcd的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05
spring boot中多線程開(kāi)發(fā)的注意事項(xiàng)總結(jié)
spring boot 通過(guò)任務(wù)執(zhí)行器 taskexecutor 來(lái)實(shí)現(xiàn)多線程和并發(fā)編程。下面這篇文章主要給大家介紹了關(guān)于spring boot中多線程開(kāi)發(fā)的注意事項(xiàng),文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-09-09
jdk中keytool的使用以及如何提取jks文件中的公鑰和私鑰
JKS文件由公鑰和密鑰構(gòu)成利用Java?Keytool工具生成的文件,它是由公鑰和密鑰構(gòu)成的,下面這篇文章主要給大家介紹了關(guān)于jdk中keytool的使用以及如何提取jks文件中公鑰和私鑰的相關(guān)資料,需要的朋友可以參考下2024-03-03
Java線程休眠_(dá)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
sleep() 的作用是讓當(dāng)前線程休眠,即當(dāng)前線程會(huì)從“運(yùn)行狀態(tài)”進(jìn)入到“休眠(阻塞)狀態(tài)”。下面通過(guò)實(shí)例代碼給大家介紹Java線程休眠的知識(shí),需要的朋友參考下吧2017-05-05
關(guān)于idea更新到2020.2.3無(wú)法創(chuàng)建web項(xiàng)目原因 library is not specified
這篇文章主要介紹了關(guān)于idea更新到2020.2.3無(wú)法創(chuàng)建web項(xiàng)目原因 library is not specified,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10

