當前位置:首頁 » 編程語言 » java深入理解

java深入理解

發布時間: 2023-06-12 21:48:54

❶ 《深入理解java虛擬機JVM高級特性與最佳實踐》epub下載在線閱讀全文,求百度網盤雲資源

《深入理解Java虛擬機(第3版)》(周志明)電子書網盤下載免費在線閱讀

鏈接: https://pan..com/s/1FEqccxQQH-AIQJE3Ishwxg

提取碼: o1cz

書名:深入理解Java虛擬機(第3版)

作者:周志明

豆瓣評分:9.5

出版社:機械工業出版社

出版年份:2019-12

頁數:540

內容簡介:

內容介紹

這是一部從工作原理和工程實踐兩個維度深入剖析JVM的著作,是計算機領域公認的經典,繁體版在台灣也頗受歡迎。

自2011年上市以來,前兩個版本累計印刷36次,銷量超過30萬冊,兩家主要網路書店的評論近90000條,內容上近乎零差評,是原創計算機圖書領域不可逾越的豐碑。

作者簡介:

資深Java技術、機器學習和企業級開發技術專家,現任遠光軟體研究院院長,人工智慧博士在讀,著有知名暢銷書《深入理解Java虛擬機:JVM高級特性與最佳實踐》。

開源技術的積極倡導者和推動者,對計算機科學和相關的多個領域都有深刻的見解,尤其是人工智慧、Java開發和敏捷開發等領域。曾受邀在InfoQ和IBM DeveloperWorks等網站撰寫技術專欄。

著作頗豐,著有《深入理解Java虛擬機》《深入理解OSGi》,翻譯了《Java虛擬機規范》等著作。其中《深入理解Java虛擬機》第1版出版於2011年,已經出至第2版,不僅銷量好,而且口碑更好,累計印刷超過30次,仍長銷不衰,是中文計算機圖書領域公認的、難得一見的佳作。


❷ 深入理解Java中為什麼內部類可以訪問外部類的成員

一般來說,外部類調用內部類的方法分為以下幾種情況:
1.使用static可以聲明一個內部類, 可以直接在外部調用

// 定義外部類
class Outer
{
// 定義外部類的私有屬性
private static String info = "hello world";
// 使用static定義內部類
static class Inner
{
// 定義內部類的方法
public void print()
{
// 直接訪問外部類的私有屬性
System.out.println(info);
}
}
// 定義外部類的方法
public void fun()
{
// 通過內部類的實例化對象調用方法
new Inner().print();
}
}

public class InnerClassDemo03
{
public static void main(String args[])
{
// 通過Outer.Inner創建內部類的實例,並調用它的print方法
new Outer.Inner().print() ;
}
}
2.不使用statc聲明一個內部類 ,使外部調用

//定義外部類
class Outer
{
//定義外部類的私有屬性
private String info = "hello world";
//定義內部類
class Inner
{
//定義內部類的方法
public void print()
{
//直接訪問外部類的私有屬性
System.out.println(info);
}
};
//定義外部類的方法
public void fun()
{
//通過內部類的實例化對象調用方法
new Inner().print();
}
};
public class InnerClassDemo04
{
public static void main(String args[])
{
//外部類實例化對象
Outer out = new Outer();
//實例化內部類對象
Outer.Inner in = out.new Inner();
//調用內部類的方法
in.print();
}
}
3.在方法中定義內部類 ,使外部調用

//定義外部類
class Outer
{
//定義外部類的私有屬性
private String info = "hello world";
//定義外部類的方法
public void fun(final int temp)
{
//在方法中定義的內部類
class Inner
{
//定義內部類的方法
public void print()
{
//直接訪問外部類的私有屬性
System.out.println("類中的屬性:" + info);
System.out.println("方法中的參數:" + temp);
}
}
//通過內部類的實例化對象調用方法
new Inner().print();
}
}

public class InnerClassDemo05
{
public static void main(String args[]){
//調用外部類的方法
new Outer().fun(30);
}
}

❸ 深入理解Java虛擬機:JVM高級特性與最佳實踐的內容簡介

作為一位java程序員,你是否也曾經想深入理解java虛擬機,但是卻被它的復雜和深奧拒之門外?沒關系,《深入理解java虛擬機:jvm高級特性與最佳實踐》極盡化繁為簡之妙,能帶領你在輕松中領略java虛擬機的奧秘。《深入理解java虛擬機:jvm高級特性與最佳實踐》是近年來國內出版的唯一一本與java虛擬機相關的專著,也是唯一一本同時從核心理論和實際運用這兩個角度去探討java虛擬機的著作,不僅理論分析得透徹,而且書中包含的典型案例和最佳實踐也極具現實指導意義。
全書共分為五大部分。第一部分從宏觀的角度介紹了整個java技術體系的過去、現在和未來,以及如何獨立地編譯一個openjdk7,這對理解後面的內容很有幫助。第二部分講解了jvm的自動內存管理,包括虛擬機內存區域的劃分原理以及各種內存溢出異常產生的原因;常見的垃圾收集演算法以及垃圾收集器的特點和工作原理;常見的虛擬機的監控與調試工具的原理和使用方法。第三部分分析了虛擬機的執行子系統,包括class的文件結構以及如何存儲和訪問class中的數據;虛擬機的類創建機制以及類載入器的工作原理和它對虛擬機的意義;虛擬機位元組碼的執行引擎以及它在實行代碼時涉及的內存結構。第四部分講解了程序的編譯與代碼的優化,闡述了泛型、自動裝箱拆箱、條件編譯等語法糖的原理;講解了虛擬機的熱點探測方法、hotspot的即時編譯器、編譯觸發條件,以及如何從虛擬機外部觀察和分析jit編譯的數據和結果。第五部分探討了java實現高效並發的原理,包括jvm內存模型的結構和操作;原子性、可見性和有序性在java內存模型中的體現;先行發生原則的規則和使用;線程在java語言中的實現原理;虛擬機實現高效並發所做的一系列鎖優化措施。
《深入理解java虛擬機:jvm高級特性與最佳實踐》適合所有java程序員、系統調優師和系統架構師閱讀。

❹ 誰有《深入理解Java虛擬機:JVM高級特性與最佳實踐-周志明》電子書百度網盤資源下載

《深入理解Java虛擬機:JVM高級特性與最佳實踐-周志明》電子書網路網盤資源下載:

鏈接: https://pan..com/s/10SXSALpvlFQzmfDOmbSqnw

提取碼: kpf4

深入理解Java虛擬機:JVM高級特性與最佳實踐-周志明

❺ 有沒有關於java深入一點的書推薦

學習的最好途徑就是看書「,這是我自己學習並且小有了一定的積累之後的第一體會。個人認為看書有兩點好處:

1.能出版出來的書一定是經過反復的思考、雕琢和審核的,因此從專業性的角度來說,一本好書的價值遠超其他資料。

2.對著書上的代碼自己敲的時候方便。

「看完書之後再次提升自我的最好途徑是看一些相關的好博文「,我個人認為這是學習的第二步,因為一本書往往有好幾百頁,好的博文是自己看書學習之後的一些總結和提煉,對於梳理學習的游蠢扮內容很有好處,當然這里不是說自己的學習方法,就不再扯下去了。

很多程序員們往往有看書的沖動,但不知道看哪些書,下面我就給各位Java程序猿們推薦一些好書(每本書的作者會加粗標紅),其中絕大多數都是我自己平時在看的書,也算是我對於平時讀的書做一個小總結和讀後感吧。

首先推薦的不是一本書,而是一個博客,也是我們博客園另外一位博友java_my_life。

目前市面上講解設計模式的書很多,雖然我前面講了看書是最好的,但是對設計模式感興趣的朋友們,我推薦的是這個博客。這位博友的設計模式講得非常非常好,我認為90%的內容都是沒有問題且很值得學習的,其講解設計模式的大體路線是:

隨便開篇點明該設計模式的定義

圖文並茂講解該設計模式中的結構

以詳細的代碼形式寫一下該種設計模式的實現

補充內容

講解該設計模式的優缺點


對於一個設計模式我們關注、學習的知識點,不就是上面這些嗎?

不過我要重點提醒一下網友們,同一種設計檔衫模式的寫法有多種,並不是說只有按某種寫法來寫才是這種設計模式。比方說適配器模式,我們關注適配器模式一定要關注的是什麼是適配器模式不是怎麼寫適配器模式,不要認為某段代碼不是按照適配器模式的寫法寫下來的它就不是適配器模式了,記住這一點,你在學習設計模式的時候一定會對代碼中用到的設計模式有更深入的理解。


1、深入理解Java虛擬機:JVM高級特性與最佳實踐


如果你不滿足於做一個只會寫ifelse的Java程序員,而是希望更進一步,我隨便舉幾個例子吧:

了解Java代碼的底層運行機制

定位性能問題

對整個系統進行性能調優

解決各種奇奇怪怪的線上線下問題

更加高級別的,為自己的項目量身定做一款適合自己項目的虛擬機

那麼Java虛擬機是你必學的一門技術。《深入理解Java虛擬機:JVM高級特性與最佳實踐》作者是周志明,這本書可以說是國內寫得最好的有關Java虛擬機的書籍,近半年,前前後後這本書我起碼看了有5遍。國內寫虛擬機的書除了這本,其實還有一些其他的,我也買過,不過粗略看下來,很多內容也是《深入理解Java虛擬機:JVM高神灶級特性與最佳實踐》此書裡面的。

另外值得一提的是,《深入理解Java虛擬機:JVM高級特性與最佳實踐》這本書,有電子版的,網上搜一下就能下載到了。不過建議有興趣的朋友還是去買書看,電子版本下載到的一般是比較老的版本,相比最新修訂版的《深入理解Java虛擬機:JVM高級特性與最佳實踐》,有很多作者新補充的知識點是沒有的。


2、HotSpot實戰


所有的Java虛擬機都是遵循著Java虛擬機規范來的,市面上的Java虛擬機幾十款,《深入理解Java虛擬機:JVM高級特性與最佳實踐》一書裡面講的虛擬機並不針對某種特定的虛擬機,而是從Java虛擬機規范的角度來講解Java虛擬機。

我們平時使用的乃至商用的大多數Java虛擬機都是Sun公司的HotSpot,大家cmd進入命令行,使用」java-version」命令就可以看到了。如果希望在Java虛擬機規范的基礎上更加深入地去理解虛擬機的一些細節是怎麼實現的,就可以看一下《HotSpot實戰》一書,作者是陳濤。不過由於HotSpot的源碼都是C/C++寫的,所以要求讀者有非常好的C/C++基礎,如果對這兩門語言不是很熟悉的朋友,看這本書可能對你幫助不是很大。

最後提一句,如果有興趣的朋友,不妨先去網上下載一個openJDK,HotSpot的源碼就在裡面。


3、Java並發編程實戰



這本書常常被列入Java程序員必讀十大書籍排行榜前幾位,不過個人不是很推薦這本書。

《Java並發編程實戰》作者是BrianGoetz,怎麼說呢,這本書前前後後我也看了兩遍左右,個人感受是:

文字多代碼少

講解多實踐少

我覺得這可能就是老外寫書的特點吧,因為Java是北美國家(加拿大、美國)開發和維護的,所以老外對Java方方面面的理論知識體系都掌握得是非常清楚和透徹的。翻開這本書看,多線程什麼用、什麼是死鎖、什麼是競爭、什麼是線程安全等等,方方面面的知識點都用大量的文字篇幅講解,不免讓人感覺十分枯燥,也難讓讀者有實質性的進步。我這本書看了兩遍也屬於一目十行意思,有興趣的地方就重點看一下。

無論如何,作為一本常常位於Jva程序員必讀十大書籍排行榜前幾名的書,還是一定要推薦給大家的。

4、java多線程編程核心技術


《Java多線程編程核心技術》作者高洪岩。想要學習多線程的朋友,這本書是我大力推薦的,我的個人博客裡面二十多篇的多線程博文都是基於此書,並且在這本書的基礎上進行提煉和總結而寫出來的。

此書和《Java並發編程實戰》相反,這本書的特點是大篇幅的代碼+小篇幅的精講解,可能這和中國人寫的書比較偏向實用主義的風格有關。本書關於線程安全、synchronized、Reentrant、Timer等等都用詳細的代碼進行了講解,而且每個大知識點下的多個小知識點都會詳細講解到,非常有實踐價值。

有興趣的朋友們,我相信只要你們跟著這本書裡面的代碼敲、運行、思考,三步走,對於多線程的使用與理解一定會進幾大步。

不過這本書的缺點就是對於Java並發包下的一些類像CountDownLatch、Semphore、CyclicBarrier、Future、Callable等都沒有講到,重點的CAS和AQS也沒有觸及,重點類的實現原理也沒有提。當然,這很深入了,在學習了這本書之後如果能再去對這些知識進行一些學習、研究的話,你一定會慢慢成長為一個很厲害的多線程高手。


5、EffectiveJava中文版


這是唯一一本我沒有買的書。初識這本書,是在我的博文Java代碼優化(長期更新)裡面,底下評論的時候有朋友提到了這本書,當時我說要去買,不過這兩個月一直都沒時間去逛書店,甚是遺憾,之後肯定會找時間去買這本書的。

《EffectiveJava中文版》的作者是JoshuaBloch,這個人就很厲害了,他是谷歌的首席架構師,屬於超級技術大牛級別了吧,呵呵。由於沒有看過這本書,所以我不好發表評論,但是從這本書的知名度以及其作者的來頭來看(多提一句,這本書也是Java之父JamesGosling博士推崇的一本書),我相信這一定是一本值得一看的好書。

好的代碼是每個Java程序員都應該去追求的,不是說我今天寫一段好代碼相比寫一段爛代碼對性能會有多大的提升,更多的應該是提升了代碼的可讀性以及可以規避許多潛在的、未知的問題,避免代碼上線之後出問題而花時間去維護—-無論從時間成本、人力成本還是風險成本來說,這都是非常高的。


6、深入分析JavaWeb技術內幕


《深入分析JavaWeb技術內幕》,作者許令波,淘寶工程師。

這本書我用一個字概括就是:全。真的非常全,HTTP、DNS、CDN、靜態化、Jetty、Tomcat、Servlet、Spring、MyBatis等等,什麼都有,涉及知識面非常廣,但又不像專門精講某個知識點的書籍一樣講得非常深入,感覺這本書就是盡量去用短的篇幅講清楚一些JavaWeb使用到的技術的內幕,讓讀者對這些知識點的技術內幕有一個理性的認識。

不過,盡管每個知識點的篇幅都不多,但是重點都基本講到了,是一本讓人真正有收獲的書。如果想進一步了解這些技術的技術內幕,就要自己去買相關書籍或者自己上網查資料了,有種拋磚引玉,或者說師傅領進門、修行在個人的感覺。


7、大型網站技術架構核心原理與案例分析


一個字評價這本書,_;兩個字評價這本書,很_;三個字評價這本書,非常_。呵呵,好了,再說下去可能別人以為我是水軍了。

《大型網站技術架構核心原理與案例分析》的作者是李智慧,原阿里巴巴技術專家。

Java的大多數應用都是用在Web上的,現在只要稍微大型一點的Web應用,都一定是一個分布式系統,那麼一個分布式系統用到了哪些技術?一個大型網站是如何從一個小型網站成長起來的?如何保證你的網站安全?分布式系統使用到了緩存,有哪些緩存?緩存的使用有哪些值得注意的事項?

關於分布式的知識點,都在這本書裡面有體現,只有你想不到,沒有他寫不到,而且寫得非常易懂,基本屬於看一兩遍,再記一些筆記就知道是怎麼一回事兒了。多看幾遍,對分布式的理解一定會加深不少。而且裡面不僅僅是分布式的知識,還非常接地氣地寫了如何做一個好的架構師,其實我認為這不僅僅是寫給想做架構師的讀者看的,就是給讀者一些建議,如何更好地提出意見、如何更讓別人關注你的聲音、如何看到他人的優點,入木三分,讓人獲益匪淺。


8、大型網站系統與Java中間件實踐


《大型網站系統與Java中間件實踐》作者曾憲傑,是淘寶的技術總監,算起來應該在阿里有至少P8的級別了吧。

這本書的部分內容和上面一本李智慧的《大型網站技術架構核心原理與案例分析》有所重合,像分布式系統的演化、CDN、CAP理論和BASE理論等等,這也更說明這些都是分布式系統或者說是一個大型網站重點關注的內容,當作一次再學習也不錯。

本書要突出的重點是中間件三個字,中間件是分布式系統中一個非常重要的東西,其最重要的作用應該就是解耦,降低模塊與模塊之間的強依賴,不同的模塊之間的依賴度降低,便可以各自獨立地開發自己的功能,這也可以說是軟體工程發展的目標和驅動力。

因此,本書有一部分的內容就是基於中間件,詳細講解了中間件與JMS的各種知識,適合對分布式系統比較熟悉並且想要往中間件方面有一定研究的讀者。


9、從Paxos到ZooKeeper分布式一致性原理與實踐


《從Paxos到ZooKeeper分布式一致性原理與實踐》,作者倪超,阿里巴巴工程師。

這本書是我最近在研讀的一本書,和上面的《大型網站系統與Java中間件實踐》一樣,屬於分布式組件的范疇,屬於有些深入的內容,當然也是我自己的個人興趣。當然,如果有志向做一個出色的大型網站架構師、公司的技術總監之類,這些知識當然是必須掌握的。

本書從分布式系統基本理論開始講起,講到Paxos演算法,最後慢慢引入到Zookeeper,循序漸進。當然,更多的我目前還不方便發表什麼看法,因為這本書的第二張Paxos演算法我都還沒有弄懂(Paxos演算法確實有些難以理解和不太易懂),接下來的章節還沒有看下去。

如果網友們所在的公司在使用Zookeeper,並且你又對Zookeeper感興趣想要研究一下它的原理的,這本書將是不二之選。


10、MySQL5.6從零開始學


《MySQL5.6從零開始學》,作者劉增傑和李坤。

作為一名Java程序員,我認為我們千萬不要覺得資料庫是DBA的事情,資料庫對一個Java程序員來說也是必須掌握的一門知識,豐富的資料庫性能優化經驗是一個頂尖程序員必備技能。

目前主流的資料庫有Oracle和MySQL,當然推薦大家的是MySQL,主要原因我認為有兩點:

1、MySQL相比Oracle更輕量級、更小、安裝和卸載更方便,SQL其實都是差不多的,如果想學資料庫,學MySQL就可以了,在家裡面可以自己方便地研究,如果你的公司使用Oracle,只要再用對比學習法,關注一下Oracle和MySQL的差別即可

2、隨著2009年阿里巴巴去IOE的運動的進行,目前國內的很多互聯網公司都會選擇MySQL作為它們使用的資料庫,因為MySQL免費,所以既省錢又不需要出了問題就依賴甲骨文公司

MySQL學習我推薦的是這本我自己學習看的《MySQL5.6從零開始學》,我是覺得挺好的這本書,書裡面的知識點很細致、很全面,讀者選擇書籍的標准大多不就是這兩點嗎?


11、Spring源碼深度解析


《Spring源碼深度解析》,作者郝佳。

Spring這個框架做得太好了,功能太強大了,以至於很多開發者都只知Spring,不知什麼是工廠、什麼是單例、什麼是代理(我面試別人的真實體會)。這種功能強大的框架內部一定是很復雜的實現,這就導致一旦你的程序使用Spring,出了問題,可能是Error、可能是Exception、可能是程序運行結果不是你的預期的,出現諸如此類問題的時候,將會讓你感到困惑,除了上網查資料或者問別人似乎沒有更好的解決辦法。

研讀Spring的源代碼不失為一種很好的學習方法,我個人認為這有很多好處:

理解框架內部的實現之後,可以主動去解決問題,而不需要依賴別人

Spring框架內部實現用到了很多設計模式,很好的代碼設計思路,這將會對你寫代碼、對你理解設計模式有很大的提高

研究Spring框架將會大大增強你讀代碼的能力,我相信只要你能研究清楚Spring內部是如何實現的,其他任何一個框架的源代碼都難不倒你

總而言之,我認為讀代碼的能力是一個普通的程序員和一個好的程序員之間最大的差別之一,前者只會把別人寫好的東西拿來用,後者不僅能用好,還清楚知道別人寫好的東西底層是如何實現的,在出現問題的時候可以輕松解決。

Spring源代碼,個人推薦《Spring源碼深度解析》一書,真要研究透並且寫清楚Spring源代碼,恐怕三四本書都不夠,作者在近400頁的篇幅中盡量去講解Spring源代碼是如何實現的,殊為不易,盡管無法講得完全,但是相信作者的講解配合上讀者自己的研究,一定可以對Spring的實現有更深度的理解。


以上就是我對Java高級部分應該看的書籍的推薦,希望可以對你有所幫助。說一點我的建議,我們學Java技術更重要的還是看視頻教程,我們只有看更多的視頻教程,不斷的練習,在腦海當中產生深刻的記憶。我永遠堅信我的一句話:書籍能詮釋的東西畢竟有限。


最後在這里推薦大家關注一下我的微信公眾號:Java新手學習,給你准備了一套最新的Java基礎精講視頻教程和Java系統學習路線,關注即可觀看。


❻ 深入Java核心 Java內存分配原理精講


Java內存分配與管理是Java的核心技術之一,今天我們深入Java核心,詳細介紹一下Java在內存分配方面的知識。一般Java在內存分配時會涉及到以下區域:
◆寄存器:我們在程序中無法控制
◆棧:存放基本類型的數據和對象的引用,但對象本身不存放在棧中,而是存放在堆中
◆堆:存放用new產生的數據
◆靜態域:存放在對象中用static定義的靜態成員
◆常量池:存放常量
◆非RAM存儲:硬碟等永久存儲空間
Java內存分配中的棧
在函數中定義的一些基本類型的變數數據和對象的引用變數都在函數的棧內存中分配。
當在一段代碼塊定義一個變數時,Java就在棧中 為這個變數分配內存空間,當該變數退出該作用域後,Java會自動釋放掉為該變數所分配的內存空間,該內存空間可以立即被另作他用。
Java內存分配中的堆
堆內存用來存放由new創建的對象和數組。 在堆中分配的內存,由Java虛擬機的自動垃圾回收器來管理。
在堆中產生了一個數組或對象弊純後,還可以 在棧中定義一個特殊的變數,讓棧中這個變數的取值等於數組或對象在堆內存中的首地址,棧中的這個變數就成了數組或租渣咐對象的引用變數。 引用變數就相當於是 為數組或對象起的一個名稱,以後就可以在程序中使用棧中的引用變數來訪問堆中的數組或對象。引用變數就相當於是為數組或者對象起的一個名稱。
引用變數是普通的變數,定義時在棧中分配,引用變數在程序運行到其作用域之外後被釋放。而數組和對象本身在堆中分配,即使程序 運行到使用 new 產生數組或者對象的語句所在的代碼塊之外,數組和對象本身占據的內存不會被釋放,數組和對象在沒有引用變數指向它的時候,才變為垃圾,不能在被使用,但仍 然占據內存空間不放,在隨後的一個不確定的時間被垃圾回收器收走(釋放掉)。這也是 Java 比較占內存的原因。
實際上,棧中的變數指向堆內存中的變數,這就是Java中的指針!
常量池 (constant pool)
常量池指的是在編譯期被確定,並被保存在已編譯的.class文件中的一些數據。除了包含代碼中所定義的各種基本類型(如int、long等等)和對象型(如String及數組)的常量值(final)還包含一些以文本形式出現的符號引用,比如:
◆類和介面的全限定名;
◆欄位的名稱和描述符;
◆方法和名稱和描述符。
虛擬機必須為每個被裝載的類型維護一個常量池。常量池就是該類型所用到常量的一個有序集和,包括直接常量(string,integer和 floating point常量)和對其他類型,欄位和方法的符號引用。
對於String常量,它的值是在常量池中的。而JVM中的常量池在內存當中是以表的形式存在的, 對於String類型,有一張固定長度的CONSTANT_String_info表用來存儲文字字元串值,注意:該表只存儲文字字元串值,不存儲符號引 用。說到這里,對常量池中的字元串值的存儲位置應該有一個比較明了的理解了。
在程序執行的時候,常量池 會儲存在Method Area,而不是堆中。
堆與棧
Java的堆是一個運行時數據區,類的(對象從中分配空間。這些對象通過new、newarray、 anewarray和multianewarray等指令建立,它們不需要程序代碼來顯式的釋放。堆是由垃圾回收來負責的,堆的優勢是可以動態地分配內存 大小,生存期也不必事先告訴編譯器,因為它是在運行時動態分配內存的,Java的垃圾收集器會自動收走這些不再使用的數據。但缺點是,由於要在運行時動態 分配內存,存取速度較慢。
棧的優勢是,存取速度比堆要快,僅次於寄存器,棧數據可以共享。但缺點是,存在棧中的數據大小與生存期必須是 確定的,缺乏靈活性。棧中主要存放一些基本類型的變數數據(int, short, long, byte, float, double, boolean, char)和對象句柄(引用)。
棧有一個很重要的特殊性,就是存在棧中的數據可以共享。假設我們同時定義:
int a = 3; int b = 3; 編譯器先處理int a = 3;梁桐首先它會在棧中創建一個變數為a的引用,然後查找棧中是否有3這個值,如果沒找到,就將3存放進來,然後將a指向3。接著處理int b = 3;在創建完b的引用變數後,因為在棧中已經有3這個值,便將b直接指向3。這樣,就出現了a與b同時均指向3的情況。
這時,如果再令 a=4;那麼編譯器會重新搜索棧中是否有4值,如果沒有,則將4存放進來,並令a指向4;如果已經有了,則直接將a指向這個地址。因此a值的改變不會影響 到b的值。
要注意這種數據的共享與兩個對象的引用同時指向一個對象的這種共享是不同的,因為這種情況a的修改並不會影響到b, 它是由編譯器完成的,它有利於節省空間。而一個對象引用變數修改了這個對象的內部狀態,會影響到另一個對象引用變數。
String是一個特殊的包裝類數據。可以用:
String str = new String("abc"); String str = "abc"; 兩種的形式來創建,第一種是用new()來新建對象的,它會在存放於堆中。每調用一次就會創建一個新的對象。而第二種是先在棧中創建一個對String類的對象引用變數str,然後通過符號引用去字元串常量池 里找有沒有"abc",如果沒有,則將"abc"存放進字元串常量池 ,並令str指向」abc」,如果已經有」abc」 則直接令str指向「abc」。
比較類裡面的數值是否相等時,用equals()方法;當測試兩個包裝類的引用是否指向同一個對象時,用==,下面用例子說明上面的理論。
String str1 = "abc"; String str2 = "abc"; System.out.println(str1==str2); //true 可以看出str1和str2是指向同一個對象的。
String str1 =new String ("abc"); String str2 =new String ("abc"); System.out.println(str1==str2); // false 用new的方式是生成不同的對象。每一次生成一個。
因此用第二種方式創建多個」abc」字元串,在內存中 其實只存在一個對象而已. 這種寫法有利與節省內存空間. 同時它可以在一定程度上提高程序的運行速度,因為JVM會自動根據棧中數據的實際情況來決定是否有必要創建新對象。而對於String str = new String("abc");的代碼,則一概在堆中創建新對象,而不管其字元串值是否相等,是否有必要創建新對象,從而加重了程序的負擔。
另 一方面, 要注意: 我們在使用諸如String str = "abc";的格式定義類時,總是想當然地認為,創建了String類的對象str。擔心陷阱!對象可能並沒有被創建!而可能只是指向一個先前已經創建的 對象。只有通過new()方法才能保證每次都創建一個新的對象。
由於String類的immutable性質,當String變數需要經常變換 其值時,應該考慮使用StringBuffer類,以提高程序效率。
1. 首先String不屬於8種基本數據類型,String是一個對象。因為對象的默認值是null,所以String的默認值也是null;但它又是一種特殊的對象,有其它對象沒有的一些特性。
2. new String()和new String(」")都是申明一個新的空字元串,是空串不是null;
3. String str=」kvill」;String str=new String (」kvill」)的區別
示例:
String s0="kvill"; String s1="kvill"; String s2="kv" + "ill"; System.out.println( s0==s1 ); System.out.println( s0==s2 ); 結果為:
true
true
首先,我們要知結果為道Java 會確保一個字元串常量只有一個拷貝。
因為例子中的 s0和s1中的」kvill」都是字元串常量,它們在編譯期就被確定了,所以s0==s1為true;而」kv」和」ill」也都是字元串常量,當一個字 符串由多個字元串常量連接而成時,它自己肯定也是字元串常量,所以s2也同樣在編譯期就被解析為一個字元串常量,所以s2也是常量池中」 kvill」的一個引用。所以我們得出s0==s1==s2;用new String() 創建的字元串不是常量,不能在編譯期就確定,所以new String() 創建的字元串不放入常量池中,它們有自己的地址空間。
示例:
String s0="kvill"; String s1=new String("kvill"); String s2="kv" + new String("ill"); System.out.println( s0==s1 ); System.out.println( s0==s2 ); System.out.println( s1==s2 ); 結果為:
false
false
false
例2中s0還是常量池 中"kvill」的應用,s1因為無法在編譯期確定,所以是運行時創建的新對象」kvill」的引用,s2因為有後半部分 new String(」ill」)所以也無法在編譯期確定,所以也是一個新創建對象」kvill」的應用;明白了這些也就知道為何得出此結果了。
4. String.intern():
再補充介紹一點:存在於.class文件中的常量池,在運行期被JVM裝載,並且可以擴充。String的 intern()方法就是擴充常量池的 一個方法;當一個String實例str調用intern()方法時,Java 查找常量池中 是否有相同Unicode的字元串常量,如果有,則返回其的引用,如果沒有,則在常 量池中增加一個Unicode等於str的字元串並返回它的引用;看示例就清楚了
示例:
String s0= "kvill"; String s1=new String("kvill"); String s2=new String("kvill"); System.out.println( s0==s1 ); System.out.println( "**********" ); s1.intern(); s2=s2.intern(); //把常量池中"kvill"的引用賦給s2 System.out.println( s0==s1); System.out.println( s0==s1.intern() ); System.out.println( s0==s2 ); 結果為:
false
false //雖然執行了s1.intern(),但它的返回值沒有賦給s1
true //說明s1.intern()返回的是常量池中"kvill"的引用
true
最後我再破除一個錯誤的理解:有人說,「使用 String.intern() 方法則可以將一個 String 類的保存到一個全局 String 表中 ,如果具有相同值的 Unicode 字元串已經在這個表中,那麼該方法返回表中已有字元串的地址,如果在表中沒有相同值的字元串,則將自己的地址注冊到表中」如果我把他說的這個全局的 String 表理解為常量池的話,他的最後一句話,」如果在表中沒有相同值的字元串,則將自己的地址注冊到表中」是錯的:
示例:
String s1=new String("kvill"); String s2=s1.intern(); System.out.println( s1==s1.intern() ); System.out.println( s1+" "+s2 ); System.out.println( s2==s1.intern() ); 結果:
false
kvill kvill
true
在這個類中我們沒有聲名一個」kvill」常量,所以常量池中一開始是沒有」kvill」的,當我們調用s1.intern()後就在常量池中新添加了一 個」kvill」常量,原來的不在常量池中的」kvill」仍然存在,也就不是「將自己的地址注冊到常量池中」了。
s1==s1.intern() 為false說明原來的」kvill」仍然存在;s2現在為常量池中」kvill」的地址,所以有s2==s1.intern()為true。
5. 關於equals()和==:
這個對於String簡單來說就是比較兩字元串的Unicode序列是否相當,如果相等返回true;而==是 比較兩字元串的地址是否相同,也就是是否是同一個字元串的引用。
6. 關於String是不可變的
這一說又要說很多,大家只 要知道String的實例一旦生成就不會再改變了,比如說:String str=」kv」+」ill」+」 「+」ans」; 就是有4個字元串常量,首先」kv」和」ill」生成了」kvill」存在內存中,然後」kvill」又和」 」 生成 「kvill 「存在內存中,最後又和生成了」kvill ans」;並把這個字元串的地址賦給了str,就是因為String的」不可變」產生了很多臨時變數,這也就是為什麼建議用StringBuffer的原 因了,因為StringBuffer是可改變的。
下面是一些String相關的常見問題:
String中的final用法和理解
final StringBuffer a = new StringBuffer("111");
final StringBuffer b = new StringBuffer("222");
a=b;//此句編譯不通過
final StringBuffer a = new StringBuffer("111");
a.append("222");// 編譯通過
可見,final只對引用的"值"(即內存地址)有效,它迫使引用只能指向初始指向的那個對象,改變它的指向會導致編譯期錯誤。至於它所指向的對象 的變化,final是不負責的。
String常量池問題的幾個例子
下面是幾個常見例子的比較分析和理解:
String a = "a1"; String b = "a" + 1; System.out.println((a == b)); //result = true String a = "atrue"; String b = "a" + "true"; System.out.println((a == b)); //result = true String a = "a3.4"; String b = "a" + 3.4; System.out.println((a == b)); //result = true 分析:JVM對於字元串常量的"+"號連接,將程序編譯期,JVM就將常量字元串的"+"連接優化為連接後的值,拿"a" + 1來說,經編譯器優化後在class中就已經是a1。在編譯期其字元串常量的值就確定下來,故上面程序最終的結果都為true。
String a = "ab"; String bb = "b"; String b = "a" + bb; System.out.println((a == b)); //result = false 分析:JVM對於字元串引用,由於在字元串的"+"連接中,有字元串引用存在,而引用的值在程序編譯期是無法確定的,即"a" + bb無法被編譯器優化,只有在程序運行期來動態分配並將連接後的新地址賦給b。所以上面程序的結果也就為false。
String a = "ab"; final String bb = "b"; String b = "a" + bb; System.out.println((a == b)); //result = true 分析:和[3]中唯一不同的是bb字元串加了final修飾,對於final修飾的變數,它在編譯時被解析為常量值的一個本地拷貝存儲到自己的常量 池中或嵌入到它的位元組碼流中。所以此時的"a" + bb和"a" + "b"效果是一樣的。故上面程序的結果為true。
String a = "ab"; final String bb = getBB(); String b = "a" + bb; System.out.println((a == b)); //result = false private static String getBB() { return "b"; } 分析:JVM對於字元串引用bb,它的值在編譯期無法確定,只有在程序運行期調用方法後,將方法的返回值和"a"來動態連接並分配地址為b,故上面 程序的結果為false。
通過上面4個例子可以得出得知:
String s = "a" + "b" + "c";
就等價於String s = "abc";
String a = "a";
String b = "b";
String c = "c";
String s = a + b + c;
這個就不一樣了,最終結果等於:
StringBuffer temp = new StringBuffer(); temp.append(a).append(b).append(c); String s = temp.toString(); 由上面的分析結果,可就不難推斷出String 採用連接運算符(+)效率低下原因分析,形如這樣的代碼:
public class Test { public static void main(String args[]) { String s = null; for(int i = 0; i
100; i++) { s += "a"; } } } 每做一次 + 就產生個StringBuilder對象,然後append後就扔掉。下次循環再到達時重新產生個StringBuilder對象,然後 append 字元串,如此循環直至結束。如果我們直接採用 StringBuilder 對象進行 append 的話,我們可以節省 N - 1 次創建和銷毀對象的時間。所以對於在循環中要進行字元串連接的應用,一般都是用StringBuffer或StringBulider對象來進行 append操作。
String對象的intern方法理解和分析:
public class Test4 { private static String a = "ab"; public static void main(String[] args){ String s1 = "a"; String s2 = "b"; String s = s1 + s2; System.out.println(s == a);//false System.out.println(s.intern() == a);//true } } 這里用到Java裡面是一個常量池的問題。對於s1+s2操作,其實是在堆裡面重新創建了一個新的對象,s保存的是這個新對象在堆空間的的內容,所 以s與a的值是不相等的。而當調用s.intern()方法,卻可以返回s在常量池中的地址值,因為a的值存儲在常量池中,故s.intern和a的值相等。
總結
棧中用來存放一些原始數據類型的局部變數數據和對象的引用(String,數組.對象等等)但不存放對象內容
堆中存放使用new關鍵字創建的對象.
字元串是一個特殊包裝類,其引用是存放在棧里的,而對象內容必須根據創建方式不同定(常量池和堆).有的是編譯期就已經創建好,存放在字元串常 量池中,而有的是運行時才被創建.使用new關鍵字,存放在堆中。

熱點內容
安卓手機已經鎖起來了怎麼刷機 發布:2025-02-13 06:35:01 瀏覽:882
安卓怎麼快速多選手機桌面圖標 發布:2025-02-13 06:21:51 瀏覽:298
androidia安裝 發布:2025-02-13 06:12:14 瀏覽:12
jsmcc文件夾 發布:2025-02-13 06:11:26 瀏覽:170
演算法與程序設計教案 發布:2025-02-13 06:10:51 瀏覽:55
ftp登錄需要輸入用戶名和密碼 發布:2025-02-13 06:03:33 瀏覽:398
數控編程代表 發布:2025-02-13 05:58:51 瀏覽:385
編程凸輪 發布:2025-02-13 05:38:21 瀏覽:691
判斷素數的編程 發布:2025-02-13 05:29:25 瀏覽:618
androidaes加密 發布:2025-02-13 05:08:36 瀏覽:493