Thinking in Java-筆記

1.P27 你擁有一個引用,並不一定需要有一個對象與之關聯。引用和對象之間的關係,好比,遙控器和電視(書上寫的),帶名的繮繩(名--引用)和馬(對象-new 出來的東西)(自己想出來的)。

---------------自我發揮---------------

String s = null;//相當於找到一個繮繩,這個繮繩是用來套馬的(定義類型),名叫s, 放在兜裏(棧),還沒有使用。

new String("I am instance 1");//相當於在草原上(堆)發現一匹馬,注意是發現,你還不能控制住它(匿名對象)。

s=new String("I am instance 2");//相當於發現一匹馬,並且用繮繩s套住了(=的意思),這個時候就可以用s這個繮繩控制這匹馬了。example: s.contains("a");

s=new String("I am instance 3");// 這個繮繩s可以套住任何一匹馬,不套剛纔的馬了,換了一匹。

-----------------------------------------

2.P28 Java的對象都存放在堆中,即使有static類型的對象,也不會存放在靜態存儲空間中。(馬這種大傢伙不能放在房子裏,應該讓它在草原上奔跑,特殊的也是馬,也是馬呀)。

3.P29 基本類型是比較小的,簡單的,用new將對象放在"堆中"並不高效,所以將其存放在棧中更好。

基本類型+引用放在棧中,相當於貓狗,小動物,在屋裏養着。

所用的對象放在堆中,相當於牛羊,大型動物,在草原上養。

4.P30 BigInteger 支持任意精度的整數。BigDecimal 支持任意精度的浮點數。

5.P31

 {

 String  s = new String ("a string")

}

引用s在作用域終點就消失了,但是,s所指String對象仍繼續佔據內存空間。

6. P33 當變量作爲類的成員使用時,Java才確保給定其默認值,以確保變量得到初始化。

7.P35 包名要小寫,歷史上出現過問題。

8. static 方法的一個重要用法就是在不創建任何對象的前提下,就可以調用它。(例如:工具類的方法Math.random())。

9. P39 java.lang 會被自動導入到每一個java文件中。

System.out 是一個靜態的PrintStream類型的對象。

10.P56 我們將布爾類型作爲一種“單比特”值對待,所以有些特別,可以對其執行按位“與”,“或”“異或”,但是不能執行按位“非”~,只能邏輯非!。

b =~b;//報錯,The operator ~ is undefined for the argument type(s) boolean

b= !b;//不報錯,!是邏輯非操作符。

11.P56 ">>"帶符號右移,“>>>”無符號右移。

如果對char,byte或者short類型的數字進行移位處理,那麼在移位進行之前,他們會被轉換爲int類型,並且得到的結果也是一個int類型。

byte b = -1;

b >>>= 5;//正確

b= b>>>5;//報錯Type mismatch: cannot convert from int to byte

只能

b= (byte) (b>>>5);//顯示強制類型轉換。

12.P60 Java 不用像C++ 那樣運算符重載。

13.P61 Java 中不會自動將 int 數值轉換成 布爾值。

while (i--) {}; //報錯,Type mismatch: cannot convert from int to boolean

14.P62 類型轉換

窄化轉換:能容納更多信息的數據類型轉化爲無法容納那麼多信息的類型(float->int),就可能面臨丟失信息的風險,必須進行顯式的轉換。

擴展轉換:上面的反過程,不會造成數據損失,不必進行顯式轉換,布爾除外。

15.P63 Java沒有sizeof,因爲市局類型在所有機器上的大小都是相同的,不需要計算。

16.P73 Java 不支持goto. 其實用label支持這種跳轉的方式。

17.只有for語句才具備在控制表達式裏定義變量的能力,其他任何條件語句或循環語句,都不可採用這種方式。

18.P79 while(true), for(;;)兩種無窮循環的方式,用break跳出。

19.P85 char c = (char) (Math.random()*26+'a');

計算過程:將一個float或者double值轉換成整數值後,總是將小數部分“砍掉”,而不是四捨五入。

20.P85 Math.random()的值域是[0.0,1)。

21.P89 在Java中,通過提供“構造器”這個特殊的方法,可以確保每個對象都會得到初始化。

22.P102 Java回收的工作原理: 一旦垃圾回收器準備好釋放對象佔有的存儲空間,將首先調用finalize(),並且在下次垃圾回收時,纔回真正回收對象佔用的內存。

C++的析構函數調用後,會直接銷燬。

Java不一樣,對象並非總是被垃圾回收。

換句話說:

對象可能不被垃圾回收,垃圾回收不等於析構。

也許你會發現,只要程序沒瀕臨存儲空間用盡的那一刻,對象佔用的空間就總也得不到釋放。如果程序執行結束,並且垃圾回收一直都沒有釋放你創建的任何對象的存儲空間,這隨着程序的退出,那些資源也會全部還給操作系統,這個策略是正確的,因爲垃圾回收本身也有開銷,要不是不使用它,那就不用支付這部分開銷。

23.P105 垃圾回收的問題,是虛擬機內部的問題,以後討論。

24.P107 對於定義在方法內部的局部變量,java以編譯時錯誤的形式來保證初始化。

int i;
int b = i+1;//The local variable i may not have been initialized

25.P108 Java中,可以在定義類成員變量的地方爲其賦值。(C++ 不能這樣做)

26. P109 無法阻止自動初始化的進行,它將在構造器被調用之前發生。

27.P109 初始化的順序

在類的內部,變量定義的先後順序決定了初始化的順序。即使變量定義散步於方法定義之間,它們讓姐會再任何方法被調用之前得到初始化。

28.P112 靜態初始化只有在必要時刻纔會執行。

什麼叫必要時刻:

1創建該類的實例

2調用該類中聲明的靜態方法

3操作該類或接口中聲明的非編譯期常量靜態字段(非final類型)

4操作特設的反射方法

5初始化該類的子類

6該類型爲虛擬機啓動時的初始化類。


總結一下對象的創建過程

1 當首次創建類A的對象時,或者A類中的靜態方法/靜態字段被訪問時java解釋器必須查找類路徑,以定位A.class文件。

2然後載入A.class(創建一個Class對象),有關靜態初始化的所有動作都會執行,因此,靜態初始化只有Class對象首次加載的時候進行一次。

3當在new A()創建對象時,首先將在堆上爲對象分配足夠的存儲空間

4這塊存儲空間會被清零,這就是自動將對象中的所有基本數據類型都設置成了缺省值,引用被設置成了null.

5執行所有出現現在字段定義處的初始化

6執行構造器

class A{
int i=10;
}

相當於
class A{
int i;
{
i=10;
}
}

29.P126 當編寫一個java源代碼文件時,此文件通常被稱爲編譯單元。每個編譯單元都必須有一個後綴名.java,而在編譯單元有一個public類,否則編譯器就不會接受。如果在編譯單元之後,還有額外的類的話,那麼在包之外的世界是無法看見這些類的,這是因爲他們不是public類,而且他們主要爲主public類提供支持。

30.P134 如果創建一個新包,並且自另外一個包繼承類,那麼唯一可以訪問的成員就是源包的public成員,當然沒如果在同一個包內執行繼承工作,可以操縱所有擁有包訪問權限的成員。

---------------------------------------

protected也提供包訪問權限,也就是說,相同包內的其他類可以訪問protected.

31.每個編譯單元(文件)都只能有一個public.

32.p141 代碼複用兩種 組合和繼承。

33.P142 初始化類中的成員類引用,可以在代碼中的下列位置進行

1 在定義對象的地方,這使他們總是能夠在構造器被調用之前被初始化。

2在類的構造器中。

3就在正要使用這個對象之前,這種方式成爲惰性初始化。

34.P145 可以爲每個類都創建一個main()。一般都建議以這種方式來編寫程序代碼,以使被包裝在類中的代碼。即使一個程序中含有多個類,也只有命令行所調用的那個累的main()方法會被調用。(類是public與否不要緊) 這種在每個類中都設置一個main()方法的技術可是每個類的單元測試變得簡單易行。

35.P146 當創建一個類的對象時,該對象包含一個基類的子對象,這個子對象與你用基類直接創建的對象是一樣的。

兩者的區別在於 後者來自於外部,而基類的子對象被包裝在導出類的對象內部。

對基類子對象的正確初始化也是至關重要的。而且也僅有一種方法來保證這一點,在構造器中,調用基類構造器來執行初始化,而基類構造器其有執行基類初始化所需要的所有知識和能力。

36.P147 缺省的構造器,即這些構造器不帶參數。編譯器可以輕鬆地調用他們是因爲不必考慮要傳遞什麼樣的參數的問題。但是,如果累沒有缺省的參數,或者必須調用一個帶參數的基類構造器,就必須用關鍵字super顯示的編寫調用基類構造器的語句。

37.P154 組合目的是新類中使用現有類的功能。

繼承的目的是新類使用現有類的接口。

38.P155 Protected 就類用戶而言,這是private的,但對於任何繼承於此類的導出類或其他任何於同一個包內的類來說,它卻是可以訪問的。

39.P158 final 數據

1一個永不改變的編譯時常量,必須是基本數據類型,同時賦值。

2一個在運行時被初始化的值,而你不希望它被改變。

40.P160 空白final. 被聲明爲final但又未給初值的字段,但編譯器都會確保空白final在使用前必須被初始化。

1.字段定義處

2.每個構造器中表達式對final賦值。

41.P161 使用final方法的原有兩個

1把方法鎖定,以防任何子類改變它的含義,不會被覆蓋。

2效率,一個方法被聲明成final,就同意編譯器將針對該方法的所有調用都轉爲內聯調用。

42P161 類中所有的private方法,隱式指定爲final的,都是無法覆蓋的。

43.P163 由於final類禁止繼承,所以final類中所有方法都隱式被指定爲final的,因爲無法覆蓋它們。

44.P164 類的代碼在初次使用時,才加載。這通常是指直到類的第一個對象被構建上才發生的。或是訪問static字段或static方法時,纔會加載的。

45.P172 將一個方法調用同一個方法主體關聯起來,被稱爲“綁定”。若在程序執行前進行綁定,叫做“前期綁定”,這是面向過程的語言中默認的綁定方式。

“後期綁定”在運行時根據對象的類型進行綁定。也叫作“動態綁定”或者“運行時綁定”。編譯器一直不知道對象的類型,但是方法調用機制能找到正確體,並加以調用。

Java 中除了static方法和final方法之外,其他所有的方法都是後期綁定的。

46.P173 爲什麼將某個方法聲明爲final呢?它可以防止其他人覆蓋方法。但是更重要一點或許是,這樣做可以“關閉”動態綁定,或者說,告訴編譯器不需要對其進行動態綁定。

47.P178 private方法被自動認爲是final的,而且對導出類是屏蔽的。在導出類有和基類private同名的方法,不屬於覆蓋。

48.P179 將類冠以抽象可以防止產生這個類的任何對象。

49.P182 構造器實際是static方法,只不過該是static是隱式的。

50.P187 初始化的實際過程

1其他任何事物發生之前,將分配到對象的存儲空間初始化成二進制的零。

2調用基類構造器。

3按照生命的順序調用成員的初始化方法。

4調用導出類的構造方法。

51.P190 純粹的繼承是is-a,實際的繼承是is-like-a.



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章