Java核心技術讀書筆記

1.  Java沒有任何unsigned類型

2.  float類型的數值後面有一個後綴F,沒有後綴F的浮點數默認爲double類型

3.  if(x = 0)在C++中可以編譯通過,其結果總爲false,而在Java中,整數表達式x = 0不能轉化爲布爾值

4.  不能使用一個未被初始化的變量

5.  使用strictfp關鍵字標記的方法或者類要使用嚴格計算,這種方式計算可能產生溢出

6.  &&和||按照短路的方式求值,如果第一個操作數已經能夠確定值,第二個操作數就不必計算&和|不是按短路運算,在得到結果之前一定要計算兩個操作數的值

7.  +=是又結合的a+=b+=c就是a+=(b+=c)

8.  代碼點和代碼單元?

9.  String對象稱爲不可改變的字符串,編譯器可以將字符串共享

10.只有字符串常量是共享的,而+或者substring等操作產生的結果都不是共享的。不要用==測試字符串的相等性,==運算符只能確定兩個字符串是不是被放置在同一個位置

11.不能在嵌套的兩個塊中聲明相同的變量,但在C++中可以

Public static void main(Stirng[] argc){

    Int n;

    {

        Intn;//這是錯誤的

}

}

12.Case標籤必須是整數或者枚舉常量,不能檢測字符串

13.帶標籤的break只能跳出程序快而不能跳入程序塊

14.兩個大數值類的應用:BigInteger和BigDecimal任意精度的數值(在java.math.*)中

15.Java中可以允許數組的長度爲0  newelementType[0]數組長度爲0和nul值不同

16.一個數組的所有元素拷貝到另一數組中的方法System.arrayCopy(from,fromIndex,to,toIndex,count);

17.Java數組與C++數組在堆棧上有很大不同,不過基本上與分配在堆上的數組指針一樣,也就是int[] a = new int[100],不同於int a[100]而等同於int * a = new int[100];

18.對數組排序使用Arrays類中的sort方法,此方法使用的快速排序

19.for each 循環訪問二維數組:

for(type[] row:Arrayname){

    for(type x:row){

        do something

}

}

20.一個對象變量並沒有實際包含一個對象,而僅僅引用一個對象,在Java中任何對象的變量都是對存儲在另外一處的一個對象的引用,new操作符的返回的值也是一個引用。下面的語句:Date deadline = new Date();有兩個部分,表達式new Date()構造了一個Date類型的對象,並且它的值是對新創對象的引用,這個引用被存儲在變量deadline中。

21.可以將Java的的對象變量看做C++的對象指針,Date birthday 等同於 Date * birthday

22.Java中所有的對象都存儲在堆中,當一個對象包含另一個對象變量時,這個變量依然包含的是指向另一個堆對象的指針。

23.對實例屬性做出修改的方法被稱爲更改器方法,僅訪問實例屬性而不加修改的方法被稱爲訪問器方法。

24.構造函數總是伴隨着new操作符的執行被調用,Java對象都是在堆中構造的

25.將某個方法設置爲內聯方法是Java虛擬機的任務

26.不要編寫返回引用可變對象的訪問器方法(get方法)。在Employee類中

class Employee{

    public Data getHireDay(){

        return hireDay;

}

}

這樣會破壞封裝性

Employee harry =...;

Date d =harry.getHireDay();

double tenYear =10 * 365.25 * 24 * 60 * 60 *1000;

d.setTime(d.getTime()– (long)tenYear);

 

出錯的原因是d和harry.hireDay引用同一個對象,對d的使用set方法就能夠自動的改變這個僱員對象的私有狀態。

如果需要返回一個可變對象的引用,應該首先對它進行克隆(clone).對象克隆指存放在另一個位置的對象副本

修改後的代碼

calss Employee{

    public Date getHireDay(){

        return (Date)hireDay.clone();

}

}

27.將屬性設置爲final,構建對象時必須初始化這樣的屬性。

28.public  staticfinal PI = 3.1415;類訪問 而public final PI= 3.1415類的實例訪問

29.System類中的setOut方法是一個本地方法,不是用Java語言實現的,本地方法可以繞過Java語言的存取控制機制

30.靜態方法是沒有this參數的方法,在一個非靜態的方法中,this參數是表示該方法的隱式參數,因爲靜態方法不能操作對象,所以不能在靜態方法中訪問非靜態屬性,但是可以訪問自身類中的靜態屬性。

31.public static getNextId(){

returnnexId;//nextId是靜態屬性

}訪問 : int n = Employee.getNextId();

在這裏是可以省略static的,但是要通過Employee類的實例來訪問

32.使用靜態方法的兩種情況:

1.  當一個方法不需要訪問對象的狀態,其所有的參數都是通過顯示參數提供的(ex:Math.pow())

2.  當一個方法只需要訪問類的靜態屬性

33.值調用表示方法接收的是調用者提供的值,而引用調用表示方法接收的是調用者提供變量的位置,Java程序設計語言使用的值調用

34.1.一個方法不能修改一個基本數據類型的參數(即數值型和布爾型值)

2.一個方法可以改變一個對象參數的狀態

3.  一個方法不能讓對象參數引用另一個新的對象

35.對象屬性和局部變量的不同之處,必須明確的初始化方法中的局部變量,但是如果沒有初始化類中的屬性,將會被初始化爲默認值(0或者false或者null)。

36.在一個構造函數中調用另一個構造函數用this(...)參數列表

37.初始化塊:首先運行初始化快,然後在運行構造函數的主體部分,建議將初始化塊放置在屬性定義之後

38.在類第一次加載的時候將會進行靜態塊的初始化,可以寫一個沒有main方法的打印

39.可以爲任何類添加finalize方法,finalize方法將在垃圾回收器清楚對象之前被調用,在實際應用中不要使用finalize方法回收任何短缺的資源,這是因爲很難知道這個方法在什麼時候被調用,有個名爲System.runFinalizersOnExit()的方法可以確保finalize在Java關閉前被調用,但是這個方法不安全,一種替代的方法是使用RunTime.addShoutdownHook()添加關閉鉤。

40.導入靜態方法和靜態屬性兩個實際應用:1.算術運算2.笨重的常量

41.沒有指定public和private,這個部分(類、方法、變量)可以被同一個包中的所有方法訪問

42.Java中所有繼承都是公用繼承

43.通過super實現對父類構造函數的調用,使用super調用構造函數的語句必須是子類構造函數的第一條語句,如果子類的構造函數沒有顯式的調用構造函數父類的構造函數,則將自動調用父類默認的構造函數。

44.this的用途:1.引用隱式參數2.調用該類的其他的構造函數

45.super的用途:1.調用父類的構造函數2.調用父類的方法

46.一個對象變量可以引用多種實際類型的現象被稱爲多態。在運行是能夠自動的選擇調用適當的方法的現象稱爲動態綁定。

47.允許子類將覆蓋方法的返回類型定義爲原返回類型的子類型

48.如果方法是private、static、final或者構造函數,那麼編輯器將可以準確的知道該調用那個方法,這種調用方式稱爲靜態綁定。

49.在覆蓋父類一個方法的時候,子類的方法不能低於父類方法的訪問權限,父類是public子類一定是public

50.阻止繼承final類和final方法,類中的方法被聲明爲final,子類就不能覆蓋這個方法,final類中的方法自動成爲final方法。但是屬性不成爲final

51.如果一個方法很短並且沒有被覆蓋,編譯器能夠對它進行優化處理這個過程稱爲內聯

52.只有在繼承層次內進行類型轉換,在將父類轉換成子類之前,應該使用instance of進行檢查。

53.如果x爲null,那麼進行x instance of C不會產生異常,只是會返回false,null沒有引用任何對象,當然也不會引用C類型的對象。

54.包含一個或者多個的抽象方法的類必須被聲明成抽象的。

55.擴展抽象類的可以有兩種選擇:一種是在子類中定義部分抽象方法或者抽象方法也不定義,這樣就必須將子類也標記成抽象類,另外一種是定義全部的抽象方法,這樣子類就不是抽象的了。

56.抽象類不能被實例化。可以定義抽象了的變量,只能夠引用非抽象子類的對象。

57.Java中protected部分對所有子類和同一包中的所有其他類可見。

58.在子類中定義equals方法時,首先要調用父類的equals方法,如果父類中的屬性都相等,就需要比較子類中的屬性

59.equals方法具有下面的特性:

1.  自反性:對於任何非空引用x,x.equals(x)應該返回true

2.  對稱性:對於任何引用x,y,如果x.equals(y)返回true那麼y.equals(x)也應該返回true

3.  傳遞性:對於任何引用x,y,z,如果x.equals(y)返回true,y.equals(z)返回true,那麼x.equals(z)也應該返回true。

4.  一致性:對於x,y引用的對象沒有發生變化,那麼反覆調用x.equals(y)應該返回相同的結果

5.  對於任何非空引用x,x.equals(null)應該返回false。

60.用instance of 用缺陷,比如說父類引用子類的對象,但是子類的對象擁有和父類某個對象相同的屬性,如果沒有考慮子類特有的信息,則instance of 就不怎麼好。

61.如果子類能夠擁有自己的相等的概念,那麼對稱性需求將強制採用getClass進行檢測。如果父類決定相等的概念,那麼就可以使用instance of進行檢測,這樣就可以在不同的子類的對象之間進行相等比較。

62.編寫完美equals方法的建議:

1.  顯示參數命名爲otherObject,稍後需要將它轉換成另一個叫做other的變量。

2.  檢測this與otherObject是否引用同一個對象:if(this == otherObject) return true;

3.  檢測otherObject是否爲null,如果爲null,返回false,這項檢測是很必要的,if(otherobjec == null) return false;

4.  比較this和otherObject是否屬於同一類,如果equals的語義在每個子類中有所改變,使用getClass檢測 

if(getClass() !=otherObject.getClass) return false;

如果所有的子類都擁有統一的語義,就是用instance of 進行檢測

if(!(otherObjectinstance of ClassName)) return false;

5.  將otherObject轉換爲相應的類類型變量:

ClassName other= (ClassName)otherObject

6.  現在開始對所有需要比較的屬性進行比較了  使用 == 比較基本類型,使equals比較對象屬性,如果所有都匹配返回true,否則返回false。

7.  如果子類中重新定義equals就要在其中包含調用super.equals().

63.hashCode方法,注意String類的hashCode方法,見源代碼。兩個相等對象要求返回相同的散列碼。

64.使用add方法爲ArrayList添加新元素,而不用set方法,它只能替換數組中已存在的元素。

65.自動裝箱與拆箱中注意基本類型與包裝器的關係,自動打包規boolean,byte,char<=127,介於-128-127之間的short和int被包裝到固定的對象中。Integer a = 100,Interger b = 100 ,a == b是成立的。但是大於127就是不成立的。

66.包含在包裝器中的內容不會改變,不能使用包裝器類創建修改數值參數的方法。

67.Class類的使用

68.異常有兩種類型,一種是未檢查異常,另一種是已檢查異常。

69.反射的機制:在java.lang.reflect包中有三個類Field,Method,Constructor分別描述類的屬性,方法和構造函數。Field中有一個getType函數,由於描述屬性所屬類型的Class類對象。Method和Constructor類含有能夠報告參數類型的方法,Method類還可以報告返回值類型,這三個類還有一個getModifiers的方法,它將返回一個整型數值,用不同的位開關設置描述public和static這些修飾符的使用狀況,還可以利用java.lang.reflect包中的Modifier類的靜態方法分析getModifiers返回的整型數值。可以使用Modifier類中的isPublic、isPrivate,isFinal判斷方法或者構造函數是否是public,private,或final。調用Modifier類的相應方法,並對getModifiers返回的整型數值進行分析,另外還可以利用Modifier.toString方法將修飾符打印出來。

70.getFields()方法返回包含Filed對象的數組,這些對象記錄了該類或其父類的公有屬性,getDeclaredField()方法返回包含Field對象的數組,這些對象記錄了該類的全部屬性。getMethod()將返回所有的公有方法,包括從父類繼承的公有方法,getDeclared()返回該類或者接口的所有方法,但是不包括由父類繼承的方法。

71.反射機制的默認行爲受限於Java的訪問控制,如果一個Java程序沒有受到安全管理器的控制,就可以覆蓋訪問控制,爲了達到目的,需要調用Field,Method,或Constructor對象的setAccessible方法。

72.爲了編寫通用擴展數組的代碼,需要能夠創建與原數組類型相同的新數組,爲此,需要java.lang.reflect包中的Array類中的一些方法,其中最關鍵的是Array類中的靜態方法newInstance,它能夠構造新數組,在調用時必須提供兩個參數,一個是數組元素的類型,另一個是數組的長度。

Object newArray= Array.newInstance(componentType,newLength)爲了執行這條語句,需要知道新數組的長度和元素類型,書上有一段很有水平的代碼,ArrayGrowTest.java

73.Java沒有提供方法指針,即將一個方法的存儲地址傳給另一個方法,以便第二個方法能夠隨後調用它。

74.Method類中的invoke方法  Objectinvoke(Object obj,Object...args)第一個參數是隱式參數,其餘的對象提供了顯式參數,以前的版本中,必須傳一個對象數組,如果沒有顯式參數就傳遞一個null,對於靜態方法,第一個參數可以被忽略,即可以將它設置爲null。Invoke的參數和返回值必須是Object類型的。

75.在比較兩個枚舉值時,永遠不需要調用equals方法,而直接使用 == 就行了。

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