




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、java內(nèi)存和基本數(shù)據(jù)類型java內(nèi)存和基本數(shù)據(jù)類型32位Intel x86最初擁有的32位物理地址僅允許處理器尋址4GB存儲空間。后來,添加了一種稱為物理地址擴(kuò)展(Physical Address Extension,PAE)的特性,將物理地址大小擴(kuò)大到了36位,允許安裝或?qū)ぶ分炼?4GB RAM。32位的操作系統(tǒng)有4GB虛擬地址空間,可以映射到一個較大的物理地址范圍.如果您將大于4GB的內(nèi)存放入32位Intel服務(wù)器中,您將無法將所有內(nèi)存直接映射到一個單一進(jìn)程中。地址窗口擴(kuò)展允許Windows進(jìn)程將其32位地址空間的一部分作為滑動窗口映射到較大的內(nèi)存區(qū)域中。這意味著盡管您無法直接引用大于4
2、GB的內(nèi)存,但您仍然可以使用較大的內(nèi)存區(qū)域。默認(rèn)情況下,32位Windows擁有2GB用戶空間和2GB內(nèi)核空間,可調(diào)整。當(dāng)執(zhí)行系統(tǒng)調(diào)用時,內(nèi)核需要訪問其自己的內(nèi)存和調(diào)用進(jìn)程的內(nèi)存。更小的用戶空間意味著應(yīng)用程序編程人員只能使用更少的內(nèi)存空間??s減內(nèi)核區(qū)域可能導(dǎo)致一些問題,比如能夠同時登錄的用戶數(shù)量限制或能夠運行的進(jìn)程數(shù)量限制。程序共享庫DLL在2G內(nèi)核空間中。盡管總體用戶空間為3GB,但是不可能分配3GB大的內(nèi)存塊,因為共享庫無法加載這么大的內(nèi)存。本機(jī)內(nèi)存泄漏或過度使用本機(jī)內(nèi)存將導(dǎo)致不同的問題,具體取決于您是耗盡了地址空間還是用完了物理內(nèi)存。耗盡地址空間通常只會發(fā)生在32位進(jìn)程上,因為最大4GB
3、的內(nèi)存很容易分配完。64位進(jìn)程具有數(shù)百或數(shù)千GB的用戶空間,即使您特意消耗空間也很難耗盡這么大的空間。如果您確實耗盡了Java進(jìn)程的地址空間,那么Java運行時可能會出現(xiàn)一些陌生現(xiàn)象,當(dāng)在進(jìn)程地址空間比物理內(nèi)存大的系統(tǒng)上運行時,內(nèi)存泄漏或過度使用本機(jī)內(nèi)存會迫使操作系統(tǒng)交換后備存儲器來用作本機(jī)進(jìn)程的虛擬地址空間。訪問經(jīng)過交換的內(nèi)存地址比讀取駐留(在物理內(nèi)存中)的地址慢得多,因為操作系統(tǒng)必須從硬盤驅(qū)動器拉取數(shù)據(jù)??赡軙峙浯罅績?nèi)存來用完所有物理內(nèi)存和所有交換內(nèi)存(頁面空間),在Linux上,這將觸發(fā)內(nèi)核內(nèi)存不足(OOM)結(jié)束程序,強(qiáng)制結(jié)束最消耗內(nèi)存的進(jìn)程。在Windows上,與地址空間被占滿時一樣
4、,內(nèi)存分配將會失敗。同時,如果嘗試使用比物理內(nèi)存大的虛擬內(nèi)存,顯然在進(jìn)程由于消耗內(nèi)存太大而被結(jié)束之前就會遇到問題。系統(tǒng)將變得異常緩慢,因為它會將大部分時間用于在內(nèi)存與交換空間之間來回復(fù)制數(shù)據(jù)。當(dāng)發(fā)生這種情況時,計算機(jī)和獨立應(yīng)用程序的性能將變得非常糟糕,從而使用戶意識到出現(xiàn)了問題。當(dāng)JVM的Java堆被交換出來時,垃圾收集器的性能會變得非常差,應(yīng)用程序可能被掛起。如果一臺機(jī)器上同時使用了多個Java運行時,那么物理內(nèi)存必須足夠分配給所有Java堆。Java運行時是一個操作系統(tǒng)進(jìn)程,它會受到我在上一節(jié)中列出的硬件和操作系統(tǒng)局限性的限制。運行時環(huán)境提供的功能受一些未知的用戶代碼驅(qū)動,這使得無法預(yù)測在
5、每種情形中運行時環(huán)境將需要何種資源。Java堆是分配了對象的內(nèi)存區(qū)域。大多數(shù)Java SE實現(xiàn)都擁有一個邏輯堆,一個物理堆可被劃分為多個邏輯扇區(qū),具體取決于用于管理堆內(nèi)存的垃圾收集(GC)算法。這些扇區(qū)通常實現(xiàn)為連續(xù)的本機(jī)內(nèi)存塊,這些內(nèi)存塊受Java內(nèi)存管理器(包含垃圾收集器)控制。大部分GC算法依賴于被分配為連續(xù)的內(nèi)存塊的堆,因此不能在堆需要擴(kuò)大時分配更多本機(jī)內(nèi)存。所有堆內(nèi)存必須預(yù)先保留。即時(JIT)編譯器JIT編譯器在運行時編譯Java字節(jié)碼來優(yōu)化本機(jī)可執(zhí)行代碼。這極大地提高了Java運行時的速度,并且支持Java應(yīng)用程序以與本機(jī)代碼相當(dāng)?shù)乃俣冗\行。字節(jié)碼編譯使用本機(jī)內(nèi)存(使用方式與gc
6、c等靜態(tài)編譯器使用內(nèi)存來運行一樣),但JIT編譯器的輸入(字節(jié)碼)和輸出(可執(zhí)行代碼)必須也存儲在本機(jī)內(nèi)存中。包含多個經(jīng)過JIT編譯的方法的Java應(yīng)用程序會使用比小型應(yīng)用程序更多的本機(jī)內(nèi)存。類和類加載器Java應(yīng)用程序由一些類組成,這些類定義對象結(jié)構(gòu)和方法邏輯。Java應(yīng)用程序也使用Java運行時類庫(比如java.lang.String)中的類,也可以使用第三方庫。這些類需要存儲在內(nèi)存中以備使用。存儲類的方式取決于具體實現(xiàn)。Sun JDK使用永久生成(permanent generation,PermGen)堆區(qū)域。Java 5的IBM實現(xiàn)會為每個類加載器分配本機(jī)內(nèi)存塊,并將類數(shù)據(jù)存儲在其
7、中?,F(xiàn)代Java運行時擁有類共享等技術(shù),這些技術(shù)可能需要將共享內(nèi)存區(qū)域映射到地址空間。要理解這些分配機(jī)制如何影響您Java運行時的本機(jī)內(nèi)存占用,您需要查閱該實現(xiàn)的技術(shù)文檔。然而,一些普遍的事實會影響所有實現(xiàn)。從最基本的層面來看,使用更多的類將需要使用更多內(nèi)存。(這可能意味著您的本機(jī)內(nèi)存使用量會增加,或者您必須明確地重新設(shè)置PermGen或共享類緩存等區(qū)域的大小,以裝入所有類)。記住,不僅您的應(yīng)用程序需要加載到內(nèi)存中,框架、應(yīng)用服務(wù)器、第三方庫以及包含類的Java運行時也會按需加載并占用空間。Java運行時可以卸載類來回收空間,但是只有在非常嚴(yán)酷的條件下才會這樣做。不能卸載單個類,而是卸載類加載
8、器,隨其加載的所有類都會被卸載。只有在以下情況下才能卸載類加載器:Java堆不包含對表示該類加載器的java.lang.ClassLoader對象的引用。Java堆不包含對表示類加載器加載的類的任何java.lang.Class對象的引用。在Java堆上,該類加載器加載的任何類的所有對象都不再存活(被引用)。需要注意的是,Java運行時為所有Java應(yīng)用程序創(chuàng)建的3個默認(rèn)類加載器(bootstrap、extension和application)都不可能滿足這些條件,因此,任何系統(tǒng)類(比如java.lang.String)或通過應(yīng)用程序類加載器加載的任何應(yīng)用程序類都不能在運行時釋放。許多JEE應(yīng)
9、用程序使用JavaServer Pages(JSP)技術(shù)來生成Web頁面。使用JSP會為執(zhí)行的每個.jsp頁面生成一個類,并且這些類會在加載它們的類加載器的整個生存期中一直存在-這個生存期通常是Web應(yīng)用程序的生存期。另一種生成類的常見方法是使用Java反射。反射的工作方式因Java實現(xiàn)的不同而不同,當(dāng)使用java.lang.reflect API時,Java運行時必須將一個反射對象(比如java.lang.reflect.Field)的方法連接到被反射到的對象或類。這可以通過使用Java本機(jī)接口(Java Native Interface,JNI)訪問器來完成,這種方法需要的設(shè)置很少,但是速
10、度緩慢。也可以在運行時為您想要反射到的每種對象類型動態(tài)構(gòu)建一個類。后一種方法在設(shè)置上更慢,但運行速度更快,非常適合于經(jīng)常反射到一個特定類的應(yīng)用程序。Java運行時在最初幾次反射到一個類時使用JNI方法,但當(dāng)使用了若干次JNI方法之后,訪問器會膨脹為字節(jié)碼訪問器,這涉及到構(gòu)建類并通過新的類加載器進(jìn)行加載。執(zhí)行多次反射可能導(dǎo)致創(chuàng)建了許多訪問器類和類加載器。保持對反射對象的引用會導(dǎo)致這些類一直存活,并繼續(xù)占用空間。因為創(chuàng)建字節(jié)碼訪問器非常緩慢,所以Java運行時可以緩存這些訪問器以備以后使用。一些應(yīng)用程序和框架還會緩存反射對象,這進(jìn)一步增加了它們的本機(jī)內(nèi)存占用。Java堆耗盡并不是造成java.la
11、ng.OutOfMemoryError的惟一原因。如果本機(jī)內(nèi)存耗盡,則會發(fā)生普通調(diào)試技巧無法解決的OutOfMemoryError。Java堆(每個Java對象在其中分配)是您在編寫Java應(yīng)用程序時使用最頻繁的內(nèi)存區(qū)域。JVM設(shè)計用于將我們與主機(jī)的特性隔離,所以將內(nèi)存當(dāng)作堆來考慮再正常不過了。您一定遇到過Java堆OutOfMemoryError,它可能是由于對象泄漏造成的,也可能是因為堆的大小不足以存儲所有數(shù)據(jù).Java應(yīng)用程序在Java運行時的虛擬化環(huán)境中運行,但是運行時本身是使用C之類的語言編寫的本機(jī)程序,它也會耗用本機(jī)資源,包括本機(jī)內(nèi)存。本機(jī)內(nèi)存是可用于運行時進(jìn)程的內(nèi)存,它與Java
12、應(yīng)用程序使用的java堆內(nèi)存不同。每種虛擬化資源(包括Java堆和Java線程)都必須存儲在本機(jī)內(nèi)存中,虛擬機(jī)在運行時使用的數(shù)據(jù)也是如此。這意味著主機(jī)的硬件和操作系統(tǒng)施加在本機(jī)內(nèi)存上的限制會影響到Java應(yīng)用程序的性能。處理器將數(shù)據(jù)流解釋為要執(zhí)行的指令,它擁有一個或多個處理單元,用于執(zhí)行整數(shù)和浮點運算以及更高級的計算。處理器具有許多寄存器-??焖俚膬?nèi)存元素,用作被執(zhí)行的計算的工作存儲,寄存器大小決定了一次計算可使用的最大數(shù)值。處理器通過內(nèi)存總線連接到物理內(nèi)存。物理地址(處理器用于索引物理RAM的地址)的大小限制了可以尋址的內(nèi)存。例如,一個16位物理地址可以尋址0x0000到0xFFFF的內(nèi)存地
13、址,這個地址范圍包括216=65536個惟一的內(nèi)存位置。如果每個地址引用一個存儲字節(jié),那么一個16位物理地址將允許處理器尋址64KB內(nèi)存。處理器被描述為特定數(shù)量的數(shù)據(jù)位。這通常指的是寄存器大小,但是也存在例外,比如32位390指的是物理地址大小。對于桌面和服務(wù)器平臺,這個數(shù)字為31、32或64;對于嵌入式設(shè)備和微處理器,這個數(shù)字可能小至4。物理地址大小可以與寄存器帶寬一樣大,也可以比它大或小。如果在適當(dāng)?shù)牟僮飨到y(tǒng)上運行,大部分64位處理器可以運行32位程序。表1.一些流行處理器架構(gòu)的寄存器和物理地址大小架構(gòu)寄存器帶寬(位)物理地址大小(位)(現(xiàn)代)Intel?x86 32 32 36,具有物理
14、地址擴(kuò)展(Pentium Pro和更高型號)x86 64 64目前為48位(以后將會增大)PPC64 64在POWER 5上為50位39031位32 31 390 64位64 64如果您編寫無需操作系統(tǒng),直接在處理器上運行的應(yīng)用程序,您可以使用處理器可以尋址的所有內(nèi)存(假設(shè)連接到了足夠的物理RAM)。但是要使用多任務(wù)和硬件抽象等特性,幾乎所有人都會使用某種類型的操作系統(tǒng)來運行他們的程序。在Windows和Linux等多任務(wù)操作系統(tǒng)中,有多個程序在使用系統(tǒng)資源。需要為每個程序分配物理內(nèi)存區(qū)域來在其中運行??梢栽O(shè)計這樣一個操作系統(tǒng):每個程序直接使用物理內(nèi)存,并且可以可靠地僅使用分配給它的內(nèi)存。一些
15、嵌入式操作系統(tǒng)以這種方式工作,但是這在包含多個未經(jīng)過集中測試的應(yīng)用程序的環(huán)境中是不切實際的,因為任何程序都可能破壞其他程序或者操作系統(tǒng)本身的內(nèi)存。虛擬內(nèi)存允許多個進(jìn)程共享物理內(nèi)存,而且不會破壞彼此的數(shù)據(jù)。在具有虛擬內(nèi)存的操作系統(tǒng)(比如Windows、Linux和許多其他操作系統(tǒng))中,每個程序都擁有自己的虛擬地址空間-一個邏輯地址區(qū)域,其大小由該系統(tǒng)上的地址大小規(guī)定(所以,桌面和服務(wù)器平臺的虛擬地址空間為31、32或64位)。進(jìn)程的虛擬地址空間中的區(qū)域可被映射到物理內(nèi)存、文件或任何其他可尋址存儲。當(dāng)數(shù)據(jù)未使用時,操作系統(tǒng)可以在物理內(nèi)存與一個交換區(qū)域(Windows上的頁面文件或者Linux上的交
16、換分區(qū))之間移動它,以實現(xiàn)對物理內(nèi)存的最佳利用率。當(dāng)一個程序嘗試使用虛擬地址訪問內(nèi)存時,操作系統(tǒng)連同片上硬件會將該虛擬地址映射到物理位置,這個位置可以是物理RAM、一個文件或頁面文件/交換分區(qū)。如果一個內(nèi)存區(qū)域被移動到交換空間,那么它將在被使用之前加載回物理內(nèi)存中。程序的每個實例以進(jìn)程的形式運行。在Linux和Windows上,進(jìn)程是一個由受操作系統(tǒng)控制的資源(比如文件和套接字信息)、一個典型的虛擬地址空間(在某些架構(gòu)上不止一個)和至少一個執(zhí)行線程構(gòu)成的集合。虛擬地址空間大小可能比處理器的物理地址大小更小。32位Intel x86最初擁有的32位物理地址僅允許處理器尋址4GB存儲空間。后來,添
17、加了一種稱為物理地址擴(kuò)展(Physical Address Extension,PAE)的特性,將物理地址大小擴(kuò)大到了36位,允許安裝或?qū)ぶ分炼?4GB RAM。PAE允許操作系統(tǒng)將32位的4GB虛擬地址空間映射到一個較大的物理地址范圍,但是它不允許每個進(jìn)程擁有64GB虛擬地址空間。這意味著如果您將大于4GB的內(nèi)存放入32位Intel服務(wù)器中,您將無法將所有內(nèi)存直接映射到一個單一進(jìn)程中。地址窗口擴(kuò)展(Address Windowing Extension)特性允許Windows進(jìn)程將其32位地址空間的一部分作為滑動窗口映射到較大的內(nèi)存區(qū)域中。Linux使用類似的技術(shù)將內(nèi)存區(qū)域映射到虛擬地址空間
18、中。這意味著盡管您無法直接引用大于4GB的內(nèi)存,但您仍然可以使用較大的內(nèi)存區(qū)域。地址空間被劃分為用戶空間和內(nèi)核空間。內(nèi)核是主要的操作系統(tǒng)程序,包含用于連接計算機(jī)硬件、調(diào)度程序以及提供聯(lián)網(wǎng)和虛擬內(nèi)存等服務(wù)的邏輯。作為計算機(jī)啟動序列的一部分,操作系統(tǒng)內(nèi)核運行并初始化硬件。一旦內(nèi)核配置了硬件及其自己的內(nèi)部狀態(tài),第一個用戶空間進(jìn)程就會啟動。如果用戶程序需要來自操作系統(tǒng)的服務(wù),它可以執(zhí)行一種稱為系統(tǒng)調(diào)用的操作與內(nèi)核程序交互,內(nèi)核程序然后執(zhí)行該請求。系統(tǒng)調(diào)用通常是讀取和寫入文件、聯(lián)網(wǎng)和啟動新進(jìn)程等操作所必需的。當(dāng)執(zhí)行系統(tǒng)調(diào)用時,內(nèi)核需要訪問其自己的內(nèi)存和調(diào)用進(jìn)程的內(nèi)存。因為正在執(zhí)行當(dāng)前線程的處理器被配置為
19、使用地址空間映射來為當(dāng)前進(jìn)程映射虛擬地址,所以大部分操作系統(tǒng)將每個進(jìn)程地址空間的一部分映射到一個通用的內(nèi)核內(nèi)存區(qū)域。被映射來供內(nèi)核使用的地址空間部分稱為內(nèi)核空間,其余部分稱為用戶空間,可供用戶應(yīng)用程序使用??蛇M(jìn)行調(diào)整來為用戶應(yīng)用程序或內(nèi)核提供更多空間。縮減內(nèi)核區(qū)域可能導(dǎo)致一些問題,比如能夠同時登錄的用戶數(shù)量限制或能夠運行的進(jìn)程數(shù)量限制。更小的用戶空間意味著應(yīng)用程序編程人員只能使用更少的內(nèi)存空間。默認(rèn)情況下,32位Windows擁有2GB用戶空間和2GB內(nèi)核空間。在32位Linux上,默認(rèn)設(shè)置為3GB用戶空間和1GB內(nèi)核空間。進(jìn)程空間必須包含程序需要的所有內(nèi)容,包括程序本身和它使用的共享庫(在W
20、indows上為DDL,在Linux上為.so文件)。共享庫不僅會占據(jù)空間,使程序無法在其中存儲數(shù)據(jù),它們還會使地址空間碎片化,減少可作為連續(xù)內(nèi)存塊分配的內(nèi)存。DLL在構(gòu)建時設(shè)置了首選的加載地址:當(dāng)加載DLL時,它被映射到處于特定位置的地址空間,除非該位置已經(jīng)被占用,在這種情況下,它會加載到別處。Windows NT最初設(shè)計時設(shè)置了2GB可用用戶空間,這對于要構(gòu)建來加載接近2GB區(qū)域的系統(tǒng)庫很有用-使大部分用戶區(qū)域都可供應(yīng)用程序自由使用。當(dāng)用戶區(qū)域擴(kuò)展到3GB時,系統(tǒng)共享庫仍然加載接近2GB數(shù)據(jù)(約為用戶空間的一半)。盡管總體用戶空間為3GB,但是不可能分配3GB大的內(nèi)存塊,因為共享庫無法加載
21、這么大的內(nèi)存。簡單的說:Java把內(nèi)存劃分成兩種:一種是棧內(nèi)存,一種是堆內(nèi)存。在函數(shù)中定義的一些基本類型的變量和對象的引用變量都在函數(shù)的棧內(nèi)存中分配。當(dāng)在一段代碼塊定義一個變量時,Java就在棧中為這個變量分配內(nèi)存空間,當(dāng)超過變量的作用域后,Java會自動釋放掉為該變量所分配的內(nèi)存空間,該內(nèi)存空間可以立即被另作他用。堆內(nèi)存用來存放由new創(chuàng)建的對象和數(shù)組。在堆中分配的內(nèi)存,由Java虛擬機(jī)的自動垃圾回收器來管理。在堆中產(chǎn)生了一個數(shù)組或?qū)ο蠛?,還可以在棧中定義一個特殊的變量,讓棧中這個變量的取值等于數(shù)組或?qū)ο笤诙褍?nèi)存中的首地址,棧中的這個變量就成了數(shù)組或?qū)ο蟮囊米兞?。引用變量就相?dāng)于是為數(shù)組或
22、對象起的一個名稱,以后就可以在程序中使用棧中的引用變量來訪問堆中的數(shù)組或?qū)ο?。具體的說:棧與堆都是Java用來在Ram中存放數(shù)據(jù)的地方。與C+不同,Java自動管理棧和堆,程序員不能直接地設(shè)置?;蚨?。Java的堆是一個運行時數(shù)據(jù)區(qū),對象從中分配空間。這些對象通過new、newarray、anewarray和multianewarray等指令建立,它們不需要程序代碼來顯式的釋放。堆是由垃圾回收來負(fù)責(zé)的,堆的優(yōu)勢是可以動態(tài)地分配內(nèi)存大小,生存期也不必事先告訴編譯器,因為它是在運行時動態(tài)分配內(nèi)存的,Java的垃圾收集器會自動收走這些不再使用的數(shù)據(jù)。但缺點是,由于要在運行時動態(tài)分配內(nèi)存,存取速度較慢。
23、棧的優(yōu)勢是,存取速度比堆要快,僅次于寄存器,棧數(shù)據(jù)可以共享。但缺點是,存在棧中的數(shù)據(jù)大小與生存期必須是確定的,缺乏靈活性。棧中主要存放一些基本類型的變量(,int,short,long,byte,float,double,boolean,char)和對象句柄。棧有一個很重要的特殊*,就是存在棧中的數(shù)據(jù)可以共享。假設(shè)我們同時定義:int a=3;int b=3;編譯器先處理int a=3;首先它會在棧中創(chuàng)建一個變量為a的引用,然后查找棧中是否有3這個值,如果沒找到,就將3存放進(jìn)來,然后將a指向3。接著處理int b=3;在創(chuàng)建完b的引用變量后,因為在棧中已經(jīng)有3這個值,便將b直接指向3。這樣,就
24、出現(xiàn)了a與b同時均指向3的情況。這時,如果再令a=4;那么編譯器會重新搜索棧中是否有4值,如果沒有,則將4存放進(jìn)來,并令a指向4;如果已經(jīng)有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。要注意這種數(shù)據(jù)的共享與兩個對象的引用同時指向一個對象的這種共享是不同的,因為這種情況a的修改并不會影響到b,它是由編譯器完成的,它有利于節(jié)省空間。而一個對象引用變量修改了這個對象的內(nèi)部狀態(tài),會影響到另一個對象引用變量。String是一個特殊的包裝類數(shù)據(jù)??梢杂茫篠tring str=new String(abc);String str=abc;兩種的形式來創(chuàng)建,第一種是用new()來新建對象的,它
25、會在存放于堆中。每調(diào)用一次就會創(chuàng)建一個新的對象。而第二種是先在棧中創(chuàng)建一個對String類的對象引用變量str,然后查找棧中有沒有存放abc,如果沒有,則將abc存放進(jìn)棧,并令str指向abc,如果已經(jīng)有abc則直接令str指向abc?;緮?shù)據(jù)類型Java中的簡單類型從概念上分為四種:實數(shù)、整數(shù)、字符、布爾值。但是有一點需要說明的是,Java里面只有八種原始類型,其列表如下:實數(shù):double、float整數(shù):byte、short、int、long字符:char布爾值:boolean復(fù)雜類型和基本類型的內(nèi)存模型本質(zhì)上是不一樣的,簡單數(shù)據(jù)類型的存儲原理是這樣的:所有的簡單數(shù)據(jù)類型不存在引用的概念
26、,簡單數(shù)據(jù)類型都是直接存儲在內(nèi)存中的內(nèi)存棧上的,數(shù)據(jù)本身的值就是存儲在??臻g里面,而Java語言里面只有這八種數(shù)據(jù)類型是這種存儲模型;而其他的只要是繼承于Object類的復(fù)雜數(shù)據(jù)類型都是按照J(rèn)ava里面存儲對象的內(nèi)存模型來進(jìn)行數(shù)據(jù)存儲的,使用Java內(nèi)存堆和內(nèi)存棧來進(jìn)行這種類型的數(shù)據(jù)存儲,簡單地講,引用是存儲在有序的內(nèi)存棧上的,而對象本身的值存儲在內(nèi)存堆上的。2)詳細(xì)介紹:Java的簡單數(shù)據(jù)講解列表如下:int:int為整數(shù)類型,在存儲的時候,用4個字節(jié)存儲,范圍為-2,147,483,648到2,147,483,647,在變量初始化的時候,int類型的默認(rèn)值為0。short:short也屬于
27、整數(shù)類型,在存儲的時候,用2個字節(jié)存儲,范圍為-32,768到32,767,在變量初始化的時候,short類型的默認(rèn)值為0,一般情況下,因為Java本身轉(zhuǎn)型的原因,可以直接寫為0。long:long也屬于整數(shù)類型,在存儲的時候,用8個字節(jié)存儲,范圍為-9,223,372,036,854,775,808到9,223,372,036,854,775,807,在變量初始化的時候,long類型的默認(rèn)值為0L或0l,也可直接寫為0。byte:byte同樣屬于整數(shù)類型,在存儲的時候,用1個字節(jié)來存儲,范圍為-128到127,在變量初始化的時候,byte類型的默認(rèn)值也為0。float:float屬于實數(shù)類型
28、,在存儲的時候,用4個字節(jié)來存儲,范圍為32位IEEEE 754單精度范圍,在變量初始化的時候,float的默認(rèn)值為0.0f或0.0F,在初始化的時候可以寫0.0。double:double同樣屬于實數(shù)類型,在存儲的時候,用8個字節(jié)來存儲,范圍為64位IEEE 754雙精度范圍,在變量初始化的時候,double的默認(rèn)值為0.0。char:char屬于字符類型,在存儲的時候用2個字節(jié)來存儲,因為Java本身的字符集不是用ASCII碼來進(jìn)行存儲,是使用的16位Unicode字符集,它的字符范圍即是Unicode的字符范圍,在變量初始化的時候,char類型的默認(rèn)值為u0000。boolean:boo
29、lean屬于布爾類型,在存儲的時候不使用字節(jié),僅僅使用1位來存儲,范圍僅僅為0和1,其字面量為true和false,而boolean變量在初始化的時候變量的默認(rèn)值為false?!?】當(dāng)整數(shù)類型的數(shù)據(jù)使用字面量賦值的時候,默認(rèn)值為int類型,就是直接使用0或者其他數(shù)字的時候,值的類型為int類型,所以當(dāng)使用long a=0這種賦值方式的時候,JVM內(nèi)部存在數(shù)據(jù)轉(zhuǎn)換?!?】當(dāng)實數(shù)類型的數(shù)據(jù)使用字面量賦值的時候,默認(rèn)值為double類型,就是當(dāng)字面兩出現(xiàn)的時候,JVM會使用double類型的數(shù)據(jù)類型?!?】從JDK 5.0開始,Java里面出現(xiàn)了自動拆箱解箱的操作,基于這點需要做一定的說明:對應(yīng)原始
30、的數(shù)據(jù)類型,每種數(shù)據(jù)類型都存在一個復(fù)雜類型的封裝類,分別為Boolean、Short、Float、Double、Byte、Int、Long、Character,這些類型都是內(nèi)置的封裝類,這些封裝類(Wrapper)提供了很直觀的方法,針對封裝類需要說明的是,每種封裝類都有一個xxxValue()的方法,通過這種方法可以把它引用的對象里面的值轉(zhuǎn)化成為原始變量的值,不僅僅如此,每個封裝類都還存在一個valueOf(String)的方法直接把字符串對象轉(zhuǎn)換為相應(yīng)的簡單類型。在JDK 5.0之前,沒有存在自動拆解箱的操作,即Auto Box操作,所以在這之前是不能使用以下方式的賦值代碼的:Intege
31、r a=0;/這種賦值方式不能夠在JDK 1.4以及以下的JDK編譯器中通過但是JDK 5.0出現(xiàn)了自動拆解箱的操作,所以在JDK 5.0以上的編譯器中,以上的代碼是可以通過的Java中簡基本數(shù)據(jù)類型的轉(zhuǎn)型:Java中的簡單數(shù)據(jù)類型的轉(zhuǎn)換分為兩種:自動轉(zhuǎn)換和強(qiáng)制轉(zhuǎn)換1)自動轉(zhuǎn)換:當(dāng)一個較小的數(shù)據(jù)和較大的數(shù)據(jù)一起運算的時候,系統(tǒng)將自動將較小的數(shù)據(jù)轉(zhuǎn)換為較大的數(shù)據(jù),再進(jìn)行運算。在方法調(diào)用過程,如果實際參數(shù)較小,而函數(shù)的形參比較大的時候,除非有匹配的方法,否則會直接使用較大的形參函數(shù)進(jìn)行調(diào)用。2)強(qiáng)制轉(zhuǎn)換:將大數(shù)據(jù)轉(zhuǎn)換為小數(shù)據(jù)時,可以使用強(qiáng)制類型轉(zhuǎn)換,在強(qiáng)制類型轉(zhuǎn)換的時候必須使用下邊這種語句:int
32、 a=(int)3.14;只是在上邊這種類型轉(zhuǎn)換的時候,有可能會出現(xiàn)精度損失。關(guān)于類型的自動提升,遵循下邊的規(guī)則:所有的byte、short、char類型的值將提升為int類型;如果有一個操作數(shù)是long類型,計算結(jié)果是long類型;如果有一個操作數(shù)是float類型,計算結(jié)果是float類型;如果有一個操作數(shù)是double類型,計算結(jié)果是double類型;自動類型轉(zhuǎn)換圖如下:byte-short(char)-int-long-float-double如果是強(qiáng)制轉(zhuǎn)換的時候,就將上邊的圖反過來當(dāng)兩個類型進(jìn)行自動轉(zhuǎn)換的時候,需要滿足條件:【1】這兩種類型是兼容的,【2】目的類型的數(shù)值范圍應(yīng)該比源轉(zhuǎn)換
33、值的范圍要大。而拓展范圍就遵循上邊的自動類型轉(zhuǎn)換樹,當(dāng)這兩個條件都滿足的時候,拓展轉(zhuǎn)換才會發(fā)生,而對于幾個原始類型轉(zhuǎn)換過程,根據(jù)兼容性boolean和char應(yīng)該是獨立的,而其他六種類型是可以兼容的,在強(qiáng)制轉(zhuǎn)換過程,唯獨可能特殊的是char和int是可以轉(zhuǎn)換的,不過會使用char的ASCII碼值比如:int a=(int)a;a的值在轉(zhuǎn)換過后輸出的話,值為97;Java提供了兩個專門的類進(jìn)行高精度運算:BigInteger與BigDecimal,雖然Java原始變量都具有對應(yīng)的封裝類型,但是這兩個變量沒有對應(yīng)的原始類型,而是通過方法來提供這兩種類型的一些運算,其含義為普通類型能夠做的操作,這兩
34、個類型對應(yīng)都有,只是因為精度過大可能效率不夠高。貨幣運算,使用BigDecimal代替double是一個很好的辦法。在要求精度答案的計算任務(wù)里面,一般慎用float和double,如果在進(jìn)行商務(wù)運算,并且要求四舍五入或者簡單的舍入行為,使用BigDecimal可能更加方便。所以盡量避免在精度運算中使用float和double,特別是我們常用的貨幣運算。string類型的字符串?dāng)?shù)組是可以無限的。字符串?dāng)?shù)組最大長度是多少?一個數(shù)組最大的長度是一個int的最大值,也就是2147483647而一個字符串在Java內(nèi)部是使用char來表示的,也就是說一個字符串的最大長度是2147483647不過這些都是
35、理論值,具體能放多少與JVM內(nèi)存有關(guān),可以在執(zhí)行java命令時加上-Xmx 1024m就將JVM內(nèi)存最大置為了1G,默認(rèn)情況下是64MB.都是java用來在RAM中存放數(shù)據(jù)的地方。與C+不同,java自動管理堆棧,程序員不能直接設(shè)置堆棧。.區(qū)別1、.棧中存放基本數(shù)據(jù)類型變量(int、float、boolean、char.)和對象句柄.堆中存放對象數(shù)據(jù)類型或者說類對象數(shù)據(jù)類型(String、基本數(shù)據(jù)類型對應(yīng)的類類型(Integer、Double.)2、.棧的存取速度比較快,僅次于寄存器,棧數(shù)據(jù)可以共享。但棧數(shù)據(jù)的大小和生存期必須是確定的,缺乏靈活性。.堆中的數(shù)據(jù)在*運行時*動態(tài)的分配內(nèi)存,存取速
36、度慢,有垃圾回收機(jī)制負(fù)責(zé)堆中的對象通過new、newarrary、anewarray和multianewarray等指令建立static Switch sw=new Switch();聲明為static的對象為靜態(tài)對象靜態(tài)對象在內(nèi)存中保留著它的引用也就是說內(nèi)存中有一塊區(qū)域就是專門用來存放靜態(tài)方法和變量的所以可以直接拿來用.是全局對象。全局對象為類間通信和函數(shù)間通信提供了一種最簡單的方式,是類的靜態(tài)成員,上面已經(jīng)提到,基類及其派生類的所有對象都共享這個靜態(tài)成員對象,所以當(dāng)需要在這些class之間或這些class objects之間進(jìn)行數(shù)據(jù)共享或通信時,這樣的靜態(tài)成員無疑是很好的選擇。棧對象的優(yōu)勢是在適當(dāng)?shù)臅r候自動生成,又在適當(dāng)?shù)臅r候自動銷毀,不需要程序員操心;而且棧對象的創(chuàng)建速度一般較堆對象快,因為分配堆對象時,會調(diào)用operator new操作,operator new會采用某種內(nèi)存空間搜索算法,而該搜索過程可能是很費時間的,產(chǎn)生棧對象則沒有這么麻煩,它僅
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 砂漿抹面施工方案
- 柱亞克力燈箱施工方案
- 展廳裝飾裝修承包合同
- 管道除銹施工方案
- 4米高圍擋施工方案
- 手球館地坪施工方案
- 房屋粉刷安裝施工方案
- 堤壩護(hù)坡混凝土施工方案
- 反光漆施工方案
- 填筑施工方案
- 家鄉(xiāng)鹽城城市介紹江蘇鹽城介紹課件
- 市政工程施工安全檢查標(biāo)準(zhǔn)
- 銀行整村授信工作經(jīng)驗材料工作總結(jié)匯報報告2篇
- 四川事業(yè)單位工作人員收入分配制度改革實施意見
- 陜西省2023第二屆長安杯大中小學(xué)國家安全知識競賽題庫及答案
- 基建礦井應(yīng)急救援預(yù)案之綜合應(yīng)急預(yù)案匯編(完整版)資料
- GA/T 830-2021尸體解剖檢驗室建設(shè)規(guī)范
- 《PEP英語六年級下冊Unit3Readandwrite》東城虎英小學(xué)王曉惠
- GB/T 3778-2021橡膠用炭黑
- GB/T 210.1-2004工業(yè)碳酸鈉及其試驗方法第1部分:工業(yè)碳酸鈉
- GB/T 19228.3-2012不銹鋼卡壓式管件組件第3部分:O形橡膠密封圈
評論
0/150
提交評論