^l : 手動換行符,即一個向下箭頭,產生辦法 shift + enter(回車)替換為“”(空。) (是字母l)
^p:自動換行符, 產生辦法:enter(回車)
保存到什么地方
程序運行時,我們最好對數據保存到什么地方做到心中有數。特別要注意的是內存的分配。有六個地方都可以保存數據:
(1) 寄存器。這是最快的保存區域,因為它位於和其他所有保存方式不同的地方:處理器內部。然而,寄存器的數量十分有限,所以寄存器是根據需要由編譯器分配。我們對此沒有直接的控制權,也不可能在自己的程序里找到寄存器存在的任何蹤跡。
(2) 堆棧。駐留於常規 RAM(隨機訪問存儲器)區域,但可通過它的“堆棧指針”獲得處理的直接支持。堆棧指針若向下移,會創建新的內存;若向上移,則會釋放那些內存。 這是一種特別快、 特別有效的數據保存方式, 僅次於寄存器。創建程序時,Java 編譯器必須准確地知道堆棧內保存的所有數據的“長度”以及“存在時間” 。這是由於它必須生成相應的代碼,以便向上和向下移動指針。這一限制無疑影響了程序的靈活性,所以盡管有些 Java 數據要保存在堆棧里——特別是對象句柄,但 Java 對象並不放到其中。
(3) 堆。一種常規用途的內存池(也在 RAM 區域) ,其中保存了 Java 對象。和堆棧不同, “內存堆”或“堆” (Heap)最吸引人的地方在於編譯器不必知道要從堆里分配多少存儲空間,也不必知道存儲的數據要在堆里停留多長的時間。因此,用堆保存數據時會得到更大的靈活性。要求創建一個對象時,只需用 new命令編制相關的代碼即可。執行這些代碼時,會在堆里自動進行數據的保存。當然,為達到這種靈活性,必然會付出一定的代價:在堆里分配存儲空間時會花掉更長的時間!
(4) 靜態存儲。這兒的“靜態” (Static)是指“位於固定位置” (盡管也在RAM 里) 。程序運行期間,靜態存儲的數據將隨時等候調用。可用 static 關鍵字指出一個對象的特定元素是靜態的。但 Java 對象本身永遠都不會置入靜態存儲空間。
(5) 常數存儲。常數值通常直接置於程序代碼內部。這樣做是安全的,因為它們永遠都不會改變。有的常數需要嚴格地保護,所以可考慮將它們置入只讀存儲器(ROM) 。
(6) 非 RAM 存儲。若數據完全獨立於一個程序之外,則程序不運行時仍可存在, 並在程序的控制范圍之外。 其中兩個最主要的例子便是 “流式對象” 和 “固定對象” 。對於流式對象,對象會變成字節流,通常會發給另一台機器。而對於固定對象,對象保存在磁盤中。即使程序中止運行,它們仍可保持自己的狀態不變。對於這些類型的數據存儲,一個特別有用的技巧就是它們能存在於其他媒體中。一旦需要,甚至能將它們恢復成普通的、基於 RAM 的對象。Java 1.1 提供了對 Lightweight persistence 的支持。未來的版本甚至可能提供更完整的方案。
java的內存機制
Java 把內存划分成兩種:一種是棧內存,另一種是堆內存。
在函數中定義的一些基本類型的變量和對象的引用變量都是在函數的棧內存中分配,當在一段代碼塊定義一個變量時,Java 就在棧中為這個變量分配內存空間,當超過變量的作用域后,Java 會自動釋放掉為該變量分配的內存空間,該內存空間可以立即被另作它用。
堆內存用來存放由 new 創建的對象和數組,在堆中分配的內存,由 Java 虛擬機的自動垃圾回收器來管理。在堆中產生了一個數組或者對象之后,還可以在棧中定義一個特殊的變量,讓棧中的這個變量的取值等於數組或對象在堆內存中的首地址,棧中的這個變量就成了數組或對象的引用變量,以后就可以在程序中使用棧中的引用變量來訪問堆中的數組或者對象,引用變量就相當於是為數組或者對象起的一個名稱。引用變量是普通的變量,定義時在棧中分配,引用變量在程序運行到其作用域之外后被釋放。而數組和對象本身在堆中分配,即使程序運行到使用 new 產生數組或者對象的語句所在的代碼塊之外,數組和對象本身占據的內存不會被釋放,數組和對象在沒有引用變量指向它的時候,才變為垃圾,不能在被使用,但仍然占據內存空間不放,在隨后的一個不確定的時間被垃圾回收器收走(釋放掉)。
這也是 Java 比較占內存的原因,實際上,棧中的變量指向堆內存中的變量,這就是 Java 中的指針!
堆棧、堆緩存方式區別
1、棧使用的是一級緩存, 他們通常都是被調用時處於存儲空間中,調用完畢立即釋放;
2、堆棧是存放在二級緩存中,生命周期由虛擬機的垃圾回收算法來決定(並不是一旦成為孤兒對象就能被回收)。所以調用這些對象的速度要相對來得低一些。
堆和棧的理論知識
1、 申請方式
堆棧: 由系統自動分配
堆:需要程序員自己申請
2.2、申請后系統的響應
堆棧:只要棧的剩余空間大於所申請空間,系統將為程序提供內存,否則將報異常提示棧溢出。
堆:首先應該知道操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然后將該結點從空閑結點鏈表中刪除,並將該結點的空間分配給程序,另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內存空間。另外,由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多余的那部 分重新放入空閑鏈表中。
2.3、申請大小的限制
堆棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩余空間時,將提示overflow。因此,能從棧獲得的空間較小。
堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲 的空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小 受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。
2.4申請效率的比較:
堆棧由系統自動分配,速度較快。但程序員是無法控制的。
堆是由new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便。
Java中的數據類型有兩種。 一種是基本類型(primitive types), 共有8種,即int, short, long, byte, float, double, boolean, char(注意,並沒有string的基本類型)。這種類型的定義是通過諸如int a = 3; long b = 255L;的形式來定義的,稱為自動變量。值得注意的是,自動變量存的是字面值,不是類的實例,即不是類的引用,這里並沒有類的存在。如int a = 3; 這里的a是一個指向int類型的引用,指向3這個字面值。這些字面值的數據,由於大小可知,生存期可知(這些字面值存儲在常數存儲區)
另一種是包裝類數據,如Integer, String, Double等將相應的基本數據類型包裝起來的類。這些類數據全部存在於堆中,Java用new()語句來顯式地告訴編譯器,在運行時才根據需要動態創建,因此比較靈活,但缺點是要占用更多的時間。
特殊情況:基本類型
有一系列類需特別對待;可將它們想象成“基本” 、 “主要”或者“主”(Primitive)類型,進行程序設計時要頻繁用到它們。之所以要特別對待,是由於用 new 創建對象(特別是小的、簡單的變量)並不是非常有效,因為 new 將對象置於“堆”里。對於這些類型,Java 采納了與 C 和 C++相同的方法。也就是說,不是用 new 創建變量,而是創建一個並非句柄的“自動”變量。這個變量容納了具體的值,並置於堆棧中,能夠更高效地存取。Java 決定了每種主要類型的大小。就象在大多數語言里那樣,這些大小並不隨着機器結構的變化而變化。這種大小的不可更改正是 Java 程序具有很強移植能力的原因之一。
主類型(放置於堆棧內) 大小 最小值 最大值 封裝器類型(放置於堆內)
boolean 1 位 - - Boolean
char 16 位 Unicode 0 Unicode 2 的 16 次方-1 Character
byte 8 位 -128 +127 Byte(注釋①)
short 16 位 -2 的 15 次方 +2 的 15 次方-1 Short(注釋①)
int 32 位 -2 的 31 次方 +2 的 31 次方-1 Integer
long 64 位 -2 的 63 次方 +2 的 63 次方-1 Long
float 32 位 IEEE754 IEEE754 Float
double 64 位 IEEE754 IEEE754 Double
Void - - - Void(注釋①)
①:到 Java 1.1 才有,1.0 版沒有。
數值類型全都是有符號(正負號)的,所以不必費勁尋找沒有符號的類型。主數據類型也擁有自己的“封裝器” (wrapper)類。這意味着假如想讓堆內一個非主要對象表示那個主類型,就要使用對應的封裝器