大二就買了這本書,如今再看這本書,看到了一些以前沒看的細節,也有了不同的體會。本文使用第4版,整理每章的筆記心得。老外的書有個特點,他會花費大量的文字去闡述一個概念,這比堆代碼強多了。
1.1 抽象
抽象是計算機最重要的概念之一。C 在解決問題時,主要是基於計算機的結構進行抽象,而不是基於所要解決的問題的結構。而 Java 則是針對問題進行建模,根據問題來描述問題,程序可以通過添加一個新類型的對象使自身適用於某個特定問題,程序員不會受限於任何特定類型的問題。
對象具有狀態、行為和標識。純粹的面向對象程序設計的基本特性:
1.2 類和對象
每個對象都是某個類的實例,一個類實際上就是一個抽象數據類型,它描述了具有相同特性(成員)和行為(功能)的對象集合。程序員可以通過定義類來適應問題,而不是被迫使用現有的用來表示機器中的存儲單元的數據類型。根據需求添加新類型擴展編程語言,系統就像對待內置類型一樣驗證並管理它們。
把對象看做是服務提供者好處:將問題分解為一系列對象的集合;提高對象的內聚性,每個對象都專注本職工作,就是高內聚性,還有個低耦合,解耦一般就用隊列實現;方便理解代碼和重用。
面向對象的特點:封裝、繼承和多態。何為封裝?即隱藏對象的屬性和細節,僅對外公開接口,控制屬性的讀取和修改。訪問控制存在的原因:隔離與提供的服務無關的部分;分離並保護接口和實現。Java 中有四種訪問權限,分別是:
1.3 代碼復用
兩種方式,組合和繼承,組合靈活性比較高,相比於繼承耦合度低一些。如果要使用某個類提供的服務功能時,一般用組合,當要是使用類提供的接口時使用繼承。
繼承,使用現有的類創建新類型。子類擁有父類的成員(public, protected)並且復制了父類的接口,也就是說,子類與父類具有相同的類型。子類有兩種方式改變自己的行為:添加新方法和覆蓋父類的方法。當添加新方法時,如果所有子類都需要,就可以把它抽取到父類中。
Java 中,Object是所有類的直接或間接父類。單根繼承的好處有:所有對象具有共用接口,利於向後兼容;所有對象都具備某些功能,易於創建和參數傳遞;易於垃圾回收。
1.6 多態
既然父類和子類是相同類型,那麼在運行時子類就能替換父類(向上轉型)來完成不同的功能,這就是多態。多態的體現是:方法的重載和覆蓋。編譯器(靜態分發,重載)和運行系統(JVM動態分發,覆蓋)會處理相關細節,保證程序正確的行為。
1.7 容器和泛型
容器,就是Java中的數據結構了,不同的容器提供不同的接口和行為,對於某些操作具有不同的效率。在JDK 5 之前容器存儲的對象是Obejct,存儲對象必須向上轉型,會丟失其身份,當取出時需要向下轉型,可能會出錯,因為不知道之前放進去的是什麼類型的對象,因此,JDK5增加了泛型,明確指出容器可接收的對象類型。
1.8 對象的創建和生命周期、異常和並發
Java 使用動態內存分配技術,使用關鍵詞 new 在堆上創建對象。使用垃圾回收器釋放對象占用的內存。
Java 內置了異常的處理,而且強制使用。異常提供了一種從錯誤進行可靠恢復的途徑。
並發控制好共享資源的訪問即可,Java提供了並發編程庫,有現成可用的並發數據結構。
1.9 Java與Internet
網絡編程會涉及到很多知識,TCP/IP,多線程,IO模型等,要寫出高性能的Java程序,還是要下大工夫的,雖然大問題被JVM搞定了。
2.1 對象
Java 通過引用來操作對象,使用 new 創建對象。那麼對象被安置在哪個地方呢?計算中有5個地方可以存儲數據,分別是:
2.2 基本類型
基本類型存儲值,並置於堆棧中,高效。Java 中基本類型的大小是固定的,不隨硬件架構的變化而變化。基本類型如下:
所有數值均有正負號,JDK5的自動包裝功能,自動地將基本類型轉為包裝類型。
高精度數字:BigInteger:支持任意精度的整數;BigDecimal:支持任意精度的定點數。
數組也是對象,能存儲基本類型和引用類型,Java會確保數組被初始化。
2.3 作用域 scope
Java 使用花括號定義作用域,局部變量在花括號結束時,生命周期就結束了,而對象不是如此,它能一直保存下去,Java通過垃圾回收器管理對象的內存。一般不會出現內存洩漏,但也不是絕對的。
2.4 類,字段,方法
使用 class 關鍵字定義一個類,類擁有字段(成員變量)和方法,對於成員變量,即使沒進行初始化,Java也會保證它有一個默認值,引用類型默認為null,數字都默認為0,布爾默認false,char默認’\u0000’(null)。對於局部變量編譯器會強制進行初始化。
方法,方法名和參數合起來稱為方法簽名,關於參數,在Java中只有值傳遞。Java消除了向前引用的問題,也就是同一個類中,成員變量和方法的先後順序可以隨意。
static關鍵字可用來修飾字段,方法和類。修飾字段方法:表示屬於類,不用新建對象就可使用。一般是修飾內部類,此類與一般的類沒有差別。
2.5 注釋
常用標簽和html如下:
3.1 優先級&賦值運算符
從左到右先乘除後加減,當不確定時,使用括號明確標識即可。
賦值運算符(=),對基本類型賦值就是把一個地方的內容復制到另一個地方,比如int a=b,就是把b的內容復制給a;對對象賦值只是使這個變量也指向該對象,比如String s = a,s和a指向同一個對象。將對象傳給方法時,也只是傳遞一個引用的值,或者說傳遞一個對象的別名。
3.2 算術、關系、邏輯運算符,直接常量
加減乘除,取模,一元加、減操作符,自增,自減。
== 作用於基本類型,比較值是否相等;作用於對象比較是否是同一個引用,比較對象使用equals,默認的equals比較引用,需要重寫。
與(&&)、或(||)、非(!)生成一個布爾值,具有短路功能,即如果第一個表達式能確定整個表達式的結果,那麼就不會運算後面的表達式。
直接常量,必須明確告訴編譯器常量類型,比如10F,10D,10L,0xFF。對於char、byte、short超過其最大范圍自動轉為int。
指數計數法:float a = 1.39E-43F;表示1.39×e^-43,如果不加F編譯器默認會當做double處理,會提示類型轉換。
3.3 位操作符和移位操作符
位操作符:
移位操作符,只能用來處理整數,char、byte、short移位時自動轉為int:
在進行移位時,比如int只有數值右端的低5位才有用,比如 16>>2 和 16>>34 相等,因為2^5=32,相當於對32取模。long類型就是低6位數字有效。
這裡多說兩句,源碼中或進行移位時會經常看到(&0xFF),原因是什麼呢?
一般我們會對字節byte進行操作,首先 0xFF 表示低8位(1字節),當對byte移位操作時,會自動轉成int,而Java中 int類型有32位,並且在計算機中數字使用有符號的二進制補碼表示。所以byte轉為int時會進行符號擴展,高位以符號位填充。如果byte為正數那麼其補碼與原碼相同,此時進不進行位與操作都無所謂,但是為負數時不同,比如byte a = -4;其轉為int在內部的表示就是11111111111111111111111111111100,這進行運算顯然是不正確的,有效位只有低八位,所以與0xFF位與運算,把高24位置0,運算結果就正確了。