盡管以C++為基礎,但是Java是一種更加純粹的面向對象的程序設計語言。
1.1用引用(句柄)操縱對象
盡管將一切都看作“對象”,但操縱的標識符實際是指向一個對象的“句柄”(引用)。
安全的做法:創建一個句柄的時候,無論如何都要進行初始化:
String str="abc";
1.2所有對象都必須創建
String s=new String("abc");
1.3 保存到什么地方
有五個地方可以保存數據
寄存器:最快的保存區域,保存在處理器內部,寄存器數量有限,根據編譯器分配。我們沒有直接的控制權,也不可能在程序里找到他存在的蹤跡。
堆棧:僅次于寄存器,存儲在常規的RAM(隨機訪問存儲器)區域,可以通過“堆棧指針”獲得處理的直接支持。堆棧指針下移會創建新的內存,上移,則會釋放那些內存。java編譯器必須知道它存儲所有數據的長度以及存在時間。由于他必須生成相應的代碼以便上移和下移,影響靈活性,盡管有些java數據保存里(特別是對象句柄),但Java對象并不放在其中。
堆:常規用途的內存池(在RAM區域),用于存放所有的java對象,堆不同于棧的好處是:編譯器不需要知道數據的存活時間。因此,在堆里面分配存儲具有很高的靈活性。但是在堆里面進行分配存儲和清理數據,會比在堆棧里面耗時。
常數存儲
非RAM存儲
作用域
1。基本類型與對象的作用域區別?
{
int x = 12;
String s = new String("a string");
}//End of scope
Java 中變量的作用域由花括號的位置決定。
對于基本類型,比如上面的 x ,一旦超出作用域,其生命周期就完結了,內存被釋放。
對于對象,只會釋放在作用域內定義的引用。比如上面創建的引用 s 在作用域終點就消失了,但指向的 String 對象仍然占據內存。如果在花括號內有把引用傳遞出去,String 對象仍是可用的,否則就繼續占著內存直至被垃圾回收器回收。
句柄s 會在作用域的終點處消失,然而,s指向的String 對象依然占據著內存空間,這段代碼,我們就無法訪問對象,因為它指向的唯一一個句柄已經在作用域的終點消失,這樣就會產生,只要我們愿意new創建的對象,只要我們愿意,就會一直保留下去,一直占據著內存空間,得不到釋放,
Java提供了一個特別的機制,“垃圾收集器”,它會查找出不被引用的new對象,釋放那些占用的內存空間。
垃圾回收機制,只知道釋放那些new分配的對象的內存,Java還提供了一種未解決特殊內存釋放的方法,finalize(),他會再垃圾回收期間提前進行一次重要的垃圾清除。
finalize():
用途:垃圾清除只跟內存有關!
2.為什么一般不要用finalize,什么時候會用到finalize?
finalize 在垃圾回收時刻提供一個清理占用的資源(特殊內存)的機會;
垃圾回收只與內存有關;
所有對象占據的內存最后都由垃圾回收器負責釋放;
Java 中一切都是對象。
既然一切都是對象,那這種特殊情況是什么鬼?
這種情況是由于分配內存時采用了類似C語言中的做法,而非Java中的通常做法,一般發生在使用“本地方法”的情況下。比如,在本地 C 方法中,可能調用了 malloc() 函數系列。
所以嘍,一般不要用 finalize 的意思是,沒有用本地方法你就基本不要用 finalize。
初始化與清理
1.為什么不能用返回值區分重載方法?
假設可以
void howAreYou(){}
int howAreYou(){
return 0;
}
void whenCanILeave(){
howAreYou();
}
事實上我們經常處于這種情況——不關心返回值是什么,只是需要調用這個函數。這時候編譯器就識別不出你要調用的到底是哪個了。所以必須依靠參數來標識一個函數。
2.對象的初始化順序?
Java 盡力保證所有變量在使用前都能得到恰當的初始化。基于這樣的思想,類的內部變量定義,即使散步于方法定義之外,仍舊會在任何方法(包括構造器)被調用前得到初始化。
明白這點,對象的初始化順序就很容易理解了:
父類靜態變量與代碼塊-->子類靜態變量與代碼塊-->父類非靜態變量與代碼塊-->父類構造器--> 子類非靜態變量與代碼塊-->子類構造器。
復用類
1.類的代碼在初次使用時才會加載
每個類的編譯代碼都存在于它自己的獨立文件中,該文件只在需要使用程序代碼時才會被加載。
這個原理的常見應用是結合靜態內部類實現延遲加載的單例模式:
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
2.final的三種情況:數據、方法和類。
final 數據:告知編譯器這塊數據是恒定不變的。final 修飾基本類型時很好理解,修飾對象的時候又怎么樣呢?效果是使得引用不可變,即無法指向另一個對象,但對于正在指向的對象自身的內容是可以改變的。
final 方法:用來鎖定方法,確保方法不會被覆蓋。在早期 final 方法還可用來提升效率,但現在已經不提倡了。所以,只有在想明確禁止覆蓋的時候,才將方法設置為 final。
private 方法默認隱式指定為final, 無法被繼承;如果子類定義相同名稱和參數的方法等同于生成了新的方法,沒有覆蓋父類設置了final的方法。
final 類:類不可繼承。