重載(overloading) (1)方法重載是讓類以統一的方式處理不同類型數據的一種手段。多個同名函數同時存在,具有不同的參數個數/類型。重載Overloading是一個類中多態性的一種表現。 (2) Java的方法重載,就是在類中可以創建多個方法,它們具有相同的名字,但具有不同的參數和不同的定義
1.重載(overloading)和重寫(overriding)
重載(overloading)
(1)方法重載是讓類以統一的方式處理不同類型數據的一種手段。多個同名函數同時存在,具有不同的參數個數/類型。重載Overloading是一個類中多態性的一種表現。
(2) Java的方法重載,就是在類中可以創建多個方法,它們具有相同的名字,但具有不同的參數和不同的定義。調用方法時通過傳遞給它們的不同參數個數和參數類型來決定具體使用哪個方法, 這就是多態性(靜態多態性)。
(3) 重載的時候,方法名要一樣,但是參數類型和個數不一樣,返回值類型可以相同也可以不相同。無法以返回型別作為重載函數的區分標準。
重寫(overriding)
(1)父類與子類之間的多態性,對父類的函數進行重新定義。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫 (Overriding)。在Java中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。但有時子類並不想原封不動地繼承父類的方法,而是想作一定的修改,這就需要採用方法的重寫。方法重寫又稱方法覆蓋。
(2)若子類中的方法與父類中的某一方法具有相同的方法名、返回類型和參數表,則新方法將覆蓋原有的方法。如需父類中原有的方法,可使用super關鍵字,該關鍵 字引用了當前類的父類。
(3)子類函數的訪問修飾許可權不能少於父類的;
根據方法的返回值區分重載方法是行不通的
類如果已經有了一個構造器(無論是否有參數),編譯器就不會幫你自動創建預設構造器
this關鍵字只能在方法內部使用,表示對‘調用方法的對象’的引用
儘管可以用this調用一個構造器,但卻不能調用兩個,必須將構造器調用置於最起始出,否則編譯器會報錯。除構造器之外,編譯器禁止在其他任何方法中調用構造器。
static關鍵字
在static方法內部不能調用非靜態方法,反過來是可以的。
方便在沒有創建對象的情況下來進行調用(方法/變數)。
很顯然,被static關鍵字修飾的方法或者變數不需要依賴於對象來進行訪問,只要類被載入了,就可以通過類名去進行訪問。
static方法一般稱作靜態方法,由於靜態方法不依賴於任何對象就可以進行訪問,因此對於靜態方法來說,是沒有this的,因為它不依附於任何對象,既然都沒有對象,就談不上this了。
另外記住,即使沒有顯示地聲明為static,類的構造器實際上也是靜態方法。
static變數也稱作靜態變數,靜態變數和非靜態變數的區別是:靜態變數被所有的對象所共用,在記憶體中只有一個副本,它當且僅當在類初次載入時會被初始化。而非靜態變數是對象所擁有的,在創建對象的時候被初始化,存在多個副本,各個對象擁有的副本互不影響。
static成員變數的初始化順序按照定義的順序進行初始化。
static塊可以置於類中的任何地方,類中可以有多個static塊。在類初次被載入的時候,會按照static塊的順序來執行每個static塊,並且只會執行一次。
為什麼說static塊可以用來優化程式性能,是因為它的特性:只會在類載入的時候執行一次。
static是不允許用來修飾局部變數。不要問為什麼,這是Java語法的規定。
常見面試題
1.下麵這段代碼的輸出結果是什麼?
public class Test extends Base{ static{ System.out.println("test static"); } public Test(){ System.out.println("test constructor"); } public static void main(String[] args) { new Test(); } } class Base{ static{ System.out.println("base static"); } public Base(){ System.out.println("base constructor"); } }
base static test static base constructor test constructor
至於為什麼是這個結果,我們先不討論,先來想一下這段代碼具體的執行過程,在執行開始,先要尋找到main方法,因為main方法是程式的入口,但是在執行main方法之前,必須先載入Test類,而在載入Test類的時候發現Test類繼承自Base類,因此會轉去先載入Base類,在載入Base類的時候,發現有static塊,便執行了static塊。在Base類載入完成之後,便繼續載入Test類,然後發現Test類中也有static塊,便執行static塊。在載入完所需的類之後,便開始執行main方法。在main方法中執行new Test()的時候會先調用父類的構造器,然後再調用自身的構造器。因此,便出現了上面的輸出結果。
1.下麵這段代碼的輸出結果是什麼?
1 public class Test { 2 Person person = new Person("Test"); 3 static{ 4 System.out.println("test static"); 5 } 6 7 public Test() { 8 System.out.println("test constructor"); 9 } 10 11 public static void main(String[] args) { 12 new MyClass(); 13 } 14 } 15 16 class Person{ 17 static{ 18 System.out.println("person static"); 19 } 20 public Person(String str) { 21 System.out.println("person "+str); 22 } 23 } 24 25 26 class MyClass extends Test { 27 Person person = new Person("MyClass"); 28 static{ 29 System.out.println("myclass static"); 30 } 31 32 public MyClass() { 33 System.out.println("myclass constructor"); 34 } 35 }
test static myclass static person static person Test test constructor person MyClass myclass constructor
類似地,我們還是來想一下這段代碼的具體執行過程。首先載入Test類,因此會執行Test類中的static塊。接著執行new MyClass(),而MyClass類還沒有被載入,因此需要載入MyClass類。在載入MyClass類的時候,發現MyClass類繼承自Test類,但是由於Test類已經被載入了,所以只需要載入MyClass類,那麼就會執行MyClass類的中的static塊。在載入完之後,就通過構造器來生成對象。而在生成對象的時候,必須先初始化父類的成員變數,因此會執行Test中的Person person = new Person(),而Person類還沒有被載入過,因此會先載入Person類並執行Person類中的static塊,接著執行父類的構造器,完成了父類的初始化,然後就來初始化自身了,因此會接著執行MyClass中的Person person = new Person(),最後執行MyClass的構造器。
垃圾回收機制
由於垃圾回收器只知道釋放那些經由new分配的記憶體,所以它不知道如何釋放該對象的這塊“特殊”記憶體(使用本地方法的情況)。為了應對這種情況,java允許在類中定義一個名為finalize()的方法。一旦垃圾回收器準備好釋放該對象占用的存儲空間,將首先調用其finalize()方法,並且在下一次垃圾回收動作發生時,才會真正回收對象占用的空間。
當垃圾回收器工作時,將一面回收空間,一面將堆中的對象緊湊排列。
引用記數是一種簡單但速度很慢的垃圾回收技術,這種方法有個缺點,如果對象之間存在迴圈引用,可能會出現“對象應該被回收,當引用不為零”的情況,未被應用於任何一種java虛擬機。
標記-清掃 所依據的思路是從堆棧和靜態存儲區出發,遍歷所有的引用,進而找到所有存活的對象。沒找到一個存活對象,就會給對象設一個標記,這個過程不會回收任何對象。只有標記工作完成後,清理工作才會開始。
初始化
無法阻止自動初始化的進行,它將在構造器調用之前發生。
在類的內部,變數定義的先後順序決定了初始化的順序。
無論創建多少個對象,靜態數據都只占用一份存儲區域。static關鍵字不能應用於局部變數。
數字初始化
int a2[]; int[] a1 = {1,2,3,4,5}; a2 = a1; for(int i = 0; i< a2.length; i++){ a2[i] = a2[i] + 1; } int[] b; Random rand = new Random(47); b = new int[rand.nextInt(20)]; System.out.print(Arrays.toString(b));
枚舉類型
enum Spiciness{ NOT,MILD,MEDIUM,HOT,FLAMING } for(Spiciness s : Spiciness.values()){ System.out.println(s +"" + s.ordinal()); } Spiciness degree; switch (degree) { case NOT: break; case MILD: break; default: break; }