字符串常量池在堆中還是方法區(qū),運行時常量池存放什么

大家好,如果您還對字符串常量池在堆中還是方法區(qū)不太了解,沒有關(guān)系,今天就由本站為大家分享字符串常量池在堆中還是方法區(qū)的知識,包括運行時常量池存放什么的問題都會給大家分析...
大家好,如果您還對字符串常量池在堆中還是方法區(qū)不太了解,沒有關(guān)系,今天就由本站為大家分享字符串常量池在堆中還是方法區(qū)的知識,包括運行時常量池存放什么的問題都會給大家分析到,還望可以解決大家的問題,下面我們就開始吧!
jvm方法區(qū)中存放的是什么東jvm方法區(qū)
方法區(qū)1.放了些什么每個類的結(jié)構(gòu)信息,運行時常量池、字段、方法數(shù)據(jù)、普通方法、構(gòu)造方法的字節(jié)碼內(nèi)容。(這是規(guī)范,不同虛擬機的實現(xiàn)是不同的最典型的就是永久代PermGenspace和元空間Metaspace)實例變量在堆內(nèi)存中,和方法區(qū)無關(guān)。2.絕對不是用來放方法的3.這塊區(qū)域所有線程共享,存在垃圾回收。
在java中為什么String字符串可以作為對象來管理
我們知道,在Java中創(chuàng)建字符串(對象)常見有多種方式:
1、Java字面量
"Java字符串"2、直接定義字符串常量
Stringstr="Java字符串";3、通過實例化String類來創(chuàng)建字符串對象
Stringstr=newString("Java字符串");而Java中的String字符串是可以直接當(dāng)成對象來操作的,這是什么原理呢?
Java中的字符串本質(zhì)上都是字符串對象像以上定義“字符串”的方式其實在Java虛擬機中都是生成了字符串對象,只不過這些字符串對象在內(nèi)存中的存取機制不同的。比如說:
1、字符串字面量、字符串常量池
Java中的字符串字面量就是一對用雙引號括起來的字符串,比如:“中國人”。
字符串常量是永生代,通俗的說就是常量池,當(dāng)遇到Stringstr="字符串"時,編譯器會在永生代中檢查是否存在這個常量的引用,若存在則直接把地址賦給棧;若不存在則先在永生代中開辟內(nèi)存空間,然后把地址賦給棧指針。
也就是說,字符串常量池中存放的依舊是字符串對象的引用。
2、實例化字符串對象
這種方式會根據(jù)String對象再次創(chuàng)建一個String對象,從堆內(nèi)存中new一塊新內(nèi)存后將指針賦給棧指針。
綜上,無論是哪種方式創(chuàng)建的字符串,其本質(zhì)依舊是字符串對象,所以在Java中字符串可以當(dāng)成對象來管理。
以上就是我的觀點,對于這個問題大家是怎么看待的呢?歡迎在下方評論區(qū)交流~我是科技領(lǐng)域創(chuàng)作者,十年互聯(lián)網(wǎng)從業(yè)經(jīng)驗,歡迎關(guān)注我了解更多科技知識!字符串常量池是在方法區(qū)中還是在獨立的區(qū)域中
Stringstr="nihao";程序開始執(zhí)行這句代碼,肯定是要創(chuàng)建一個對象的,只是這個對象創(chuàng)建后就是一個常量,不可以更改,并且這個對象是放在串池里面的,也就是你說的那個常量池
如果我后面在寫一句代碼:Stringother="nihao";
str和other這2個引用的地址就是一樣的,因為str和other的聲明方式是一樣的,都是在串池,str的對象創(chuàng)建時,串池中沒有"nihao"這個常量,就創(chuàng)建一個.other對象創(chuàng)建時,發(fā)現(xiàn)串池中已經(jīng)有了"nihao"這個常量,就直接拿過來用就是了
Stringa1=newString("nihao");
Stringb1=newString("nihao");
但是如果我們通過上面的方式直接newString()那個a1和b1這2個引用的對象就不是在串池中了,而是在堆中,但是newString()的參數(shù)"nihao"也是一個字符串啊,這個字符串從哪里來呢?如果我們吧代碼拆分一下就明白了:
Stringpara="nihao";
Stringa1=newString(para);
就會發(fā)現(xiàn)Stringa1=newString("nihao");這一句代碼實際上創(chuàng)建了2個對象,一個是String對象,存放在堆中,一個是字符串常量對象,存放在串池中
Java中的字符串常量池與Java中的堆和棧的區(qū)別
java常量池不在堆中也不在棧中,是獨立的內(nèi)存空間管理。
1.棧:存放基本類型的變量數(shù)據(jù)和對象的引用,但對象本身不存放在棧中,而是存放在堆(new出來的對象)或者常量池中(字符串常量對象存放在常量池中。)
2.堆:存放所有new出來的對象。
3.常量池:存放字符串常量和基本類型常量(publicstaticfinal)。
對于字符串:其對象的引用都是存儲在棧中的,如果是編譯期已經(jīng)創(chuàng)建好(直接用雙引號定義的)的就存儲在常量池中,如果是運行期(new出來的)才能確定的就存儲在堆中。對于equals相等的字符串,在常量池中永遠(yuǎn)只有一份,在堆中有多份。
為什么String在java中是不可變的
String類在Java中被設(shè)計成不可變的,這是Java開發(fā)人員大家都知道的事情。但是要讓大家真的說出來為什么String在Java中是不可變的,有時候真的能讓人一時語塞,或者說的不夠全面。這個問題有各種提問的方式,例如:“為什么Java中要把String類設(shè)計成不可變的?”,“String類被設(shè)計成不可變類有什么好處?”基本上都是一個思路。
接下來個人從以下幾個方面來談?wù)勛约簩@個問題的看法:
什么是不可變?《EffectiveJava》中對于不可變類的解釋如下:
不可變類只是其實例不能被修改的類。每個實例中包含的所有信息都必須在創(chuàng)建該實例的時候就提供,并且在對象的整個生命周期內(nèi)固定不變。為了使類不可變,要遵循下面五條規(guī)則:
1.不要提供任何會修改對象狀態(tài)的方法。
2.保證類不會被擴展。一般的做法是讓這個類稱為的,防止子類化,破壞該類的不可變行為。
3.使所有的域都是final的。
4.使所有的域都成為私有的。防止客戶端獲得訪問被域引用的可變對象的權(quán)限,并防止客戶端直接修改這些對象。
5.確保對于任何可變性組件的互斥訪問。如果類具有指向可變對象的域,則必須確保該類的客戶端無法獲得指向這些對象的引用。
不可變帶來的好處多線程安全:不可變對象天生多線程安全。因為不可變對象不會被改變,所以它們可以被多線程共享,不需要增加額外的同步操作。字符串池:上面的代碼只會創(chuàng)建一個對象實例到JavaHeap中,當(dāng)創(chuàng)建str1時候,會去字符串池中查看是否已經(jīng)有了這個字符串,如果有,那么把str1的引用直接指向這個字符串實例上去,這樣便極大的節(jié)省了內(nèi)存空間的使用。如果字符串可變的話,那么修改了其中一個對象,就會影響另外一個。
緩存HashCode
當(dāng)我們創(chuàng)建了一個字符串對象時候,便生成了它的HashCode,因為是不可變,所以生成之后便可以緩存起來,這樣用于HashMap中的key,便大大提高了查詢的速度。還有我們的Set集合,大家都知道Set集合是不可重復(fù)的集合,String類的不可變很好的支持了Set集合的設(shè)計思想。String類是基石正是因為有了以String類為代表的這些不可變類,才能為其他對象的構(gòu)建提供了極大的便利,想想我們在編寫Java程序的時候,是不是大量的使用了String類。
以上,就是我個人對Java中為什么String類是不可變的幾點看法,大家還有什么更好的見解?歡迎討論交流,批評指正~
方法區(qū)與永久區(qū)的區(qū)別
方法區(qū)(MethodArea)是jvm規(guī)范里面的運行時數(shù)據(jù)區(qū)的一個組成部分,jvm規(guī)范中的運行時數(shù)據(jù)區(qū)還包含了:pc寄存器、虛擬機棧、堆、方法區(qū)、運行時常量池、本地方法棧
永久區(qū)也就是永久帶,又叫Perm區(qū),只存在于hotspotjvm中,并且只存在于jdk7和之前的版本中,jdk8中已經(jīng)徹底移除了永久帶,jdk8中引入了一個新的內(nèi)存區(qū)域叫metaspace
文章到此結(jié)束,如果本次分享的字符串常量池在堆中還是方法區(qū)和運行時常量池存放什么的問題解決了您的問題,那么我們由衷的感到高興!
本文鏈接:http://m.tiantaijiaoyu.cn/kaifa/4017.html