摘要:今天看到了一個(gè)的相關(guān)問(wèn)題,解決問(wèn)題的過(guò)程中就想把好好理順了,總結(jié)在這里。查看的構(gòu)造函數(shù)源碼可見(jiàn)為了使的線程安全性在構(gòu)造時(shí)得到延續(xù),加了同步塊。可見(jiàn)指向同一個(gè)對(duì)象。
今天看到了一個(gè)Java string的相關(guān)問(wèn)題,解決問(wèn)題的過(guò)程中就想把string 好好理順了,總結(jié)在這里。
== 和 equals()== 是判斷兩個(gè)變量是否指向同一個(gè)對(duì)象,equals()只判斷兩個(gè)字符串內(nèi)容是否相同
public class Cons { public static void main(String[] args) throws InterruptedException { String s2 = new String("vv"); String s3 = "vv"; System.out.println(s2 == s3);//false System.out.println(s3.equals(s2));//true } }String、StringBuilder和StringBuffer
String和StringBuilder:StringBuilder是可變的,也就是說(shuō)用StringBuilder創(chuàng)建的字符串你可以隨時(shí)改變它。
StringBuilder和StringBuffer:StringBuffer是同步的,它是線程安全(thread-safe)的,但效率要比StringBuilder差得多。
查看String的構(gòu)造函數(shù)jdk源碼:
public String(StringBuffer buffer) { synchronized(buffer) { this.value = Arrays.copyOf(buffer.getValue(), buffer.length()); } } public String(StringBuilder builder) { this.value = Arrays.copyOf(builder.getValue(), builder.length()); }
可見(jiàn) 為了使buffer的線程安全性在構(gòu)造String時(shí)得到延續(xù),加了同步塊。
String str = new String("vv"); 創(chuàng)建了幾個(gè)對(duì)象?答案:1或2
new String("vv")在堆中創(chuàng)建了1個(gè)實(shí)例對(duì)象,而另1個(gè)就是放在常量池中的 "vv" 對(duì)象,當(dāng)然這里的str本身 只是一個(gè)引用,放在棧里,用來(lái)指向堆中創(chuàng)建出來(lái)的對(duì)象。所以如果常量池已經(jīng)有"vv" 對(duì)象,就只在堆中創(chuàng)建一個(gè)對(duì)象;如果還沒(méi)有,就會(huì)放入常量池,然后再在堆中創(chuàng)建一個(gè)對(duì)象,怎么驗(yàn)證呢?
public class Cons { public static void main(String[] args) throws InterruptedException { String s1 = new String("vv"); String s2 = "vv"; System.out.println(s1 == s2);//false } }
然后用命令行工具( 深入理解Java虛擬機(jī) 一書(shū)中看的工具)
可見(jiàn)常量池中有一個(gè)String 類型的 對(duì)象 vv,而且new出來(lái)的對(duì)象不是指向常量池的那個(gè)對(duì)象,亦即新創(chuàng)建了一個(gè)
注:jdk1.7 以后,虛擬機(jī)把存儲(chǔ)Java對(duì)象的地方定義為堆,其它地方是不會(huì)有Java對(duì)象的實(shí)體的。故常量池不再存儲(chǔ)對(duì)象實(shí)例,而是存儲(chǔ)的引用,實(shí)際對(duì)象還是在堆中,所以有所不同,下文不再贅述。
String str = "vv"; 創(chuàng)建了幾個(gè)對(duì)象?答案:0或1
如果常量池已經(jīng)有"vv" 對(duì)象,就直接返回引用,如果還沒(méi)有,就會(huì)放入常量池,然后返回引用。
public class Cons { public static void main(String[] args) throws InterruptedException { String s1 = "vv"; String s2 = "vv"; System.out.println(s1 == s2);//true } }
可見(jiàn)s1,s2指向同一個(gè)對(duì)象。
而且常量池也有 vv
String str = "v" + "v";創(chuàng)建了幾個(gè)對(duì)象?答案:0或1
常量字符串是在編譯的時(shí)候就被確定的,"v"是常量,所以編譯時(shí)確定
這個(gè)代碼編譯后 與 String str = "vv"; 是一樣的
public class Cons { public static void main(String[] args) throws InterruptedException { String s1 = "vv"; String s2 = "v"+"v"; System.out.println(s1 == s2);//true } }
可見(jiàn) s1,s2 指向同一個(gè)對(duì)象
String str = s1 + s2;創(chuàng)建了幾個(gè)對(duì)象?答案 視情況而定
“+”連接的兩個(gè)字符串本身就是字面常量字符串時(shí),如果池中存在這樣連接后的字符串,則是不會(huì)重新創(chuàng)建對(duì)象,而是直接引用池中的字符串對(duì)象;如果“+”連接的兩字符串中只要有一個(gè)是變量,是會(huì)產(chǎn)生新的字符串對(duì)象。
public class Cons { public static void main(String[] args) throws InterruptedException { String s1 = "ww"; String s2 = "vv"; String s3 = "vvww"; String s4 = "vv"+"ww"; String s5 = "vv"+s1; System.out.println(s3 == s4);//true System.out.println(s3 == s5);//false } }
但是如果變量是常量時(shí),就不同了
public class Cons { public static void main(String[] args) throws InterruptedException { final String s1 = "ww"; String s2 = "vv"; String s3 = "vvww"; String s4 = "vv"+"ww"; String s5 = "vv"+s1; String s6 = s2+s1; System.out.println(s3 == s4);//true System.out.println(s3 == s5);//true } }
但如果先定義final字符串,但未在定義處初始化,那么又不同了,
public class Cons { public static void main(String[] args) throws InterruptedException { final String s1 ; String s2 = "vv"; String s3 = "vvww"; String s4 = "vv"+"ww"; s1 = "ww"; String s5 = "vv"+s1; String s6 = s2+s1; System.out.println(s3 == s4);//true System.out.println(s3 == s5);//false } }
因?yàn)閟1是在運(yùn)行過(guò)程確定的,所以s5也只能運(yùn)行時(shí)確定;
總結(jié)起來(lái), String str=s1+s2 創(chuàng)建幾個(gè)變量,關(guān)鍵取決于 s1,s2 能否在編譯期確定
public class Cons { public static void main(String[] args) throws InterruptedException { String s1 = new String("vv"); String s2 = "v".concat("v"); String s4 = "v"+"v"; String s3 = "vv"; System.out.println(s2 == s3);//false System.out.println(s1 == s3);//false System.out.println(s4 == s3);//true } }
可見(jiàn)concat 產(chǎn)生的變量沒(méi)有直接引用常量池的對(duì)象。
查看jdk8源碼
public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true); }
果然是新創(chuàng)建了一個(gè) String對(duì)象。
String 和 Char[]查看jdk源碼,知道 String的內(nèi)部實(shí)現(xiàn)就是一個(gè) Char 數(shù)組, 說(shuō)String 不可變,也是因?yàn)?這個(gè)數(shù)組就是一個(gè)final 類型的 變量。
未完待續(xù)......參考
http://jiangzhengjun.iteye.co...
《深入理解Java虛擬機(jī)》
歡迎訪問(wèn)我的個(gè)人主頁(yè) mageek(mageek.cn)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/69999.html
摘要:創(chuàng)建一個(gè)可緩存線程池,如果線程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線程,若無(wú)可回收,則新建線程。創(chuàng)建一個(gè)定長(zhǎng)線程池,支持定時(shí)及周期性任務(wù)執(zhí)行。 轉(zhuǎn)載請(qǐng)注明原創(chuàng)地址為:http://www.54tianzhisheng.cn/... 線程池 Wiki 上是這樣解釋的:Thread Pool showImg(https://segmentfault.com/img/remote/146000...
摘要:所有示例代碼請(qǐng)見(jiàn)下載于基本概念并發(fā)同時(shí)擁有兩個(gè)或者多個(gè)線程,如果程序在單核處理器上運(yùn)行多個(gè)線程將交替地?fù)Q入或者換出內(nèi)存這些線程是同時(shí)存在的,每個(gè)線程都處于執(zhí)行過(guò)程中的某個(gè)狀態(tài),如果運(yùn)行在多核處理器上此時(shí),程序中的每個(gè)線程都 所有示例代碼,請(qǐng)見(jiàn)/下載于 https://github.com/Wasabi1234... showImg(https://upload-images.jians...
摘要:事件只能攜帶一個(gè)的。例如在上述代碼示例中的將所有使用發(fā)布事件的地方,全部修改為使用的方法。是否能夠編寫(xiě)腳本或者自動(dòng)化工具,自動(dòng)化的完成重構(gòu)工作。實(shí)施方案使用注解解析自動(dòng)生成文件我們都知道,是通過(guò)注解來(lái)實(shí)現(xiàn)的。 歡迎大家前往騰訊云社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~ 作者:吳濤 導(dǎo)語(yǔ):EventBus 已經(jīng)火了很長(zhǎng)一段時(shí)間了。最近我們項(xiàng)目決定引入EventBus,替換我們播放器現(xiàn)在的事...
摘要:?jiǎn)栴}來(lái)源今天與同學(xué)聊天,得知他有個(gè)任務(wù)是抓取同花順網(wǎng)站上的股票數(shù)據(jù),有點(diǎn)興趣,便做了相關(guān)實(shí)驗(yàn)。由于時(shí)間關(guān)系,以上代碼只是把數(shù)據(jù)所在的網(wǎng)頁(yè)抓取到本地,沒(méi)有進(jìn)行解析。 問(wèn)題來(lái)源 今天與同學(xué)聊天,得知他有個(gè)任務(wù)是抓取同花順網(wǎng)站上的股票數(shù)據(jù),有點(diǎn)興趣,便做了相關(guān)實(shí)驗(yàn)。 介紹 網(wǎng)站地址:http://q.10jqka.com.cn/ 網(wǎng)站界面:showImg(https://segmentf...
摘要:可空性在中,類型系統(tǒng)區(qū)分一個(gè)引用是可以容納可空引用還是不能容納非空引用。使用可以很方便得將可空轉(zhuǎn)為非空,但可空變量值為,則會(huì)。 目錄介紹 01.可空性 02.安全調(diào)用運(yùn)算符:?. 03.Elvis運(yùn)算符:?: 04.安全轉(zhuǎn)換運(yùn)算符:as? 05.非空斷言:!! 06.let函數(shù)說(shuō)明 07.可空類型的擴(kuò)展 08.Java中判斷方式 09.kotlin是否解決NPE 10.kotlin如...
閱讀 3078·2021-11-24 09:38
閱讀 1330·2021-09-22 15:27
閱讀 2968·2021-09-10 10:51
閱讀 1504·2021-09-09 09:33
閱讀 917·2021-08-09 13:47
閱讀 2072·2019-08-30 13:05
閱讀 892·2019-08-29 15:15
閱讀 2425·2019-08-29 12:21