《Java編程思想》讀書筆記-對象導論

計算機是頭腦延伸的工具,是一種不一樣類型的表達媒體。本文以背景性的和補充性的材料,介紹包括開發方法概述在內的面向對象程序設計(Object-oriented Programming,OOP)的基本概念。

本文經過概念+代碼的方式,來幫助讀者瞭解面向對象程序設計的全貌。java

抽象過程

概念

機器模型:位於解空間內,是對問題建模的地方;能夠這樣理解,彙編語言和命令式語言,在解決問題時要基於計算機的架構;所以架構限定了解決方案,因此說機器模型是解空間。程序員

實際待解決問題:問題空間,是問題存在的地方編程

如何抽象

抽象的類型和質量,決定了人們所可以解決的問題的複雜性。抽象的類型指的是「所抽象的是什麼」。一種是在機器模型和實際待解決問題的模型之間創建聯繫的抽象;另外一種是隻針對待解決問題建模。而面向對象則是向程序員提供表示問題空間中元素的工具,咱們將問題空間中的元素及其在解空間中的表示稱爲「對象」。微信

面向對象程序設計的特性:
  1. 萬物皆是對象;
  2. 程序是對象的集合,對象間方法的調用是程序運行的基本表現;
  3. 對象能夠包含其餘對象;
  4. 每一個對象都擁有其特定的類型;
  5. 某一特定類型的全部對象均可以接收一樣的方法調用;
什麼是對象?對象具備狀態、行爲和標識。每個對象均可以擁有內部數據和方法,而且能夠惟一的與其餘對象區分開來

每一個對象都應該都歸屬於一個類或接口

名詞解釋

對象:具備狀態、行爲和標識的實體。如銀行存款帳戶是一個類,那麼具體的每一個人的銀行存款帳戶就是這個類目下的對象。多線程

類:能夠看做類型來考慮。好比說鳥類,是動物中的其中一種類型。架構

類和對象
全部的對象都是惟一的,但同時具備相同的特性和行爲的對象也都歸屬於某個特定的類。

類在Java中用關鍵詞class表示。每一個類的對象都具備某種共性和個性,如銀行存款帳戶,每一個帳戶中都有餘額的屬性,但每一個帳戶中的餘額又不一樣。在實際中,面向對象程序設計語言都用class關鍵字來表示數據類型,換而言之,每個類都是一個數據類型。程序員能夠自由地添加新的類(數據類型)來擴展編程語言,對實際問題進行處理。併發

對象的獲取與方法調用

面向對象的挑戰之一,就是在問題空間的元素和解空間的對象之間建立一對一的映射。編程語言

獲取有用對象,必須以某種方式對對象進行請求,使對象完成各類任務。類型決定接口,而接口決定對象能知足的請求。就好比鳥類型,其提供的接口有飛翔,所以其能知足飛翔的請求。在接口肯定了某一特定對象可以發出的請求後,接口的實現掌控着請求的具體行爲的展示方式。在類型中,每個可能的請求都有一個方法與之關聯,當向對象發送請求時,與之關聯的方法就會被調用。函數

如下代碼是獲取一個對象並調用其中的方法實例(你能夠暫時不用理解,只須要知道形式便可,後面再反過來看就好)工具

public class Light {
 //開燈
 public void on() {
   System.out.println("Light is on!");
 }
 //關燈
 public void off() {
   System.out.println("Light is off!");
 }

 //這裏是獲取一個對象並調用其中方法的實例
 public static void main(String [] args) {
   //這裏是核心代碼,開燈操做
   Light lt = new Light();
   lt.on();
 }
}

### 對象是服務提供者

程序經過調用其餘對象提供的服務來向用戶提供服務。程序員的目標就是去建立(或者最好是從現有的代碼庫中尋找)可以提供解決問題所需服務的一系列對象。

爲何要把對象看做是服務提供者呢?

  • 這是將問題分解爲對象集合的一種合理方式。好比說,你正在建立一個簿記系統,那麼,這個系統能夠拆分爲:我須要一個包括了預約義的簿記輸入屏幕的對象、一個執行簿記計算的對象集合以及一個處理在不一樣的打印機上打印支票和開發票的對象。
  • 它有助於提升對象的內聚性。就像上面所定義的簿記系統,每一個對象均可以很好地完成一項任務,可是它並不試圖作更多的事情。職能太多,可能會致使對象的內聚性下降。簡而言之,每一個對象只作它該作的事。

程序訪問權限控制

將程序開發人員按照角色劃分爲 類建立者客戶端程序員。類建立者建立新的數據類型,而客戶端程序員在其應用中使用類建立者建立的新數據類型。如此一來,客戶端程序員的主要目的就是收集各類用來實現快速應用開發的類;而類建立者的目的則是構建類,並向客戶端程序員暴露必須的部分。

爲何類建立者須要對類的某些部分進行隱藏呢?或者說,爲何須要進行訪問權限控制呢?

  • 讓客戶端程序員沒法觸及他們不應觸及的部分,讓客戶端程序員分清楚,哪些東西對他們來講是必須的,哪些是能夠忽略的。
  • 容許庫設計者能夠改變類內部的工做方式而不用擔憂會影響到客戶端程序員。由於對客戶端程序員所提供的那一部分可見的內容老是不變的,而庫設計者改變的是其中隱藏的部分。
Java的訪問權限控制關鍵字
修飾符 類內部 同包 子類 任何地方
private × × ×
× ×
protected ×
public
訪問權限關鍵字的修飾範圍
  • public:能夠修飾外部類、屬性、方法;
  • protected:只能修飾屬性和方法;
  • private:只能修飾屬性、方法、內部類;

複用具體實現

代碼複用是面向對象程序設計語言所提供的最了不得的優勢之一。

代碼複用的基本方式:

  • 直接使用該類的一個對象;
  • 能夠將某個類的一個對象置於一個新類中,做爲新類的成員出現;

類之家的關係

關係是指事物之間存在單向或者相互的做用力或者影響力的狀態。

在兩個類之間存在有關係和不要緊兩種狀況,在有關係的狀況下,其關係包括如下六種類型

類關係 英文名 描述 強權方 UML圖表示 示例說明
繼承 extends 父類與子類之間的關係:is-a 父類 空心三角+實線,空心三角指向父類 鳥是動物
實現 implements 接口與實現類之間的關係:can-do 接口 空心三角+虛線,空心三角指向接口 鳥實現了飛翔的接口
組合 composition 比聚合更強的關係:contains-a 總體 實心菱形+實線,實心菱形指向總體 人類的頭和身體是強組合關係
聚合 aggregation 暫時組裝的關係:has-a 組裝方 空心菱形+實線,空心菱形指向組裝方 狗和牽狗的繩子是聚合關係
依賴 dependency 一個類依賴於另外一個類:depends-a 被依賴方 箭頭+虛線,箭頭指向被依賴方 人喂小狗,小狗是喂這個動做的被依賴方
關聯 association 類與類之間存在互相平等的使用關係:links-a 平等 實線 人與信用卡的關係,人用信用卡,信用卡能夠讀取我的信息

繼承關係

以現有類爲基礎,複製它,而後經過添加和修改這個副原本建立新類。當源類發生變化時,被修改的副本也會反應出這種變更。生物學中對科目的定義,用於解釋繼承關係再恰當不過。
相關名詞定義

父類:又稱源類、基類、超類;

子類:又稱導出類、繼承類;

父類和子類

父類和子類之間的類型層次結構同時體現了他們之間的類似性和差別性。當繼承現有類型時,也就創造了新的類型,同時子類又歸屬於父類的類型。這個新的類型不只包括現有類型的全部成員,並且更重要的是它複製了父類的接口,這意味着全部對父類對象的調用同時可能夠對子類對象發起,這遵循了編程原則之一的里氏替換原則。

若是隻是簡單地繼承一個類而不作其餘任何事情,那麼在父類接口中的方法將會直接繼承到子類中。當須要使父類和子類產生差別時,有如下兩種方式:

  • 直接在子類中添加新的方法;在採用該種方案時須要仔細考慮是否存在父類也須要這些額外方法的可能性。
  • 覆寫父類中的某個方法;該種方案須要在子類中定義與父類需覆寫方法同名、同返回值類型、同方法參數類型的方法。

那麼繼承是否應該只覆寫父類的方法呢?

若是繼承只覆寫了父類的方法,那麼子類對象能夠徹底替代父類對象,這一般稱之爲替代原則,在這種狀況下的類關係稱爲is-a;但有時又的確須要在子類中添加新的接口,這種狀況下父類沒法訪問新添加的接口,這種狀況下類關係爲is-like-a,這時這種父類與子類之間的關係,被視爲非存粹替代

多態

在處理類層次關係的時候,若是把任意一個特定類型的對象能夠看成其基類對象來對待,就使得人們能夠編寫出不依賴於特定類型的代碼。
相關概念

前期綁定:編譯器將產生對一個具體函數名字的調用,而在運行時須要將這個調用解析到將要被執行的代碼的絕對地址(意味着運行前就須要知道具體代碼的位置)。

後期綁定:編譯器只確保調用的方法存在,並且調用參數和返回值類型正確;在運行時,經過特殊代碼,解析具體將要執行的代碼的具體位置。

多態的實現理念

經過導出新的子類而輕鬆擴展設計的能力,是對改動進行封裝的基本方式之一。

在試圖將子類對象看成其基類對象來看待時,須要解決的一個問題是:編譯器沒法精確地瞭解哪一段代碼將會被執行。在OOP程序設計中,程序直到運行時纔可以肯定代碼的位置。

OOP程序設計語言使用了後期綁定的概念:編譯器確保調用方法的存在,並對調用參數和返回值執行類型檢查,但並不知道將被執行的確切代碼。Java使用一小段特殊的代碼來替代絕對地址調用,這段特殊代碼用來計算方法體的具體位置。Java默認是動態綁定的。

向上轉型

把子類對象看做父類對象的過程,稱做向上轉型。緣由是在類圖中,父類老是位於類圖的頂部,把子類對象視爲父類對象,即將子類類型向上推導。

單根繼承

Java中全部的類最終都繼承自單一的基類:Object

單根繼承結構保證全部對象都具有某些功能。Object是任何類的默認父類,是在哲學方向上繼續寧的延伸思考。

  1. 我是誰?getClass()說明本質上是誰,而toString()是當前類的名片。
  2. 我從哪裏來?Object()構造方法是生產對象的基本方式;clone()是繁殖對象的另外一種方式。
  3. 我到哪裏去?finalize()方法說明了對象的最終歸屬
  4. 我是不是獨一無二的?hashCode()和equals()就是判斷與其餘元素是否相同的一組方法。
  5. 與其餘人如何協調?wait()和notify()方法是對象間通訊和協做的一組方法。

容器

一般來講,若是不知道在解決某個特定問題時須要多少對象,或者他們將存活多久,那麼就不可能知道如何存儲這些對象。

在Java標準類庫中提供了大量容器。不一樣的容器提供了不一樣類型的接口和外部行爲,同時對某些操做具備不一樣的效率。如List中的ArrayList和LinkedList因爲底層實現的不一樣,具有不一樣的應用場景。

參數化類型

因爲容器只存儲Object,因此將對象引入置入容器時,被向上轉型爲Object,在取出類型時會丟失其類型。在必定程度上可使用向下轉型的方式來獲取其實際類型,可是這樣作存在風險。

package a;

import java.util.*;

public class Container {
  public static void main(String [] args) {
    List list = new ArrayList();
    list.add("Hello World!");
    list.add(1);
    //程序運行到這裏是不會報錯的,可是執行下面這一步的時候,就會出現異常了
    for(Object o : list) {
      //這一步會出現異常,由於List中存放的不只僅是String類型,還有Integer類型,向下轉型出現異常
      String a = (String) o;
      System.out.println(a);
    }
  }
}

那麼用什麼方式使容器記住這些對象究竟使什麼類型呢?解決方案稱爲參數化類型,在Java中也稱爲泛型。表示方法爲一對尖括號,中間包含類型信息。

List<String> list = new ArrayList<String>();

這樣一來,就限定了List中只能存放String類型的對象啦!固然,咱們仍是可以經過反射繞過這層驗證,畢竟在編譯後運行時,是去泛型的。

對象的建立和生命週期

在使用對象時,最關鍵的問題之一即是他們的生成和銷燬方式。
對象的建立

new Constructor();:經過new關鍵詞向堆中申請內存,經過Constructor來講明類的建立方式。

生命週期

Java採用動態內存分配的方式。動態方式有個通常性假設:對象趨於變得複雜,因此查找和釋放內存空間的開銷不會對對象的建立形成重大沖擊。動態方式所帶來的更大的靈活性是解決通常化編程問題的要點。

Java提供了被稱爲垃圾收集器的機制,用來處理內存釋放問題。垃圾收集器的運行基礎是單根繼承結構只能在堆上建立對象的特性。

異常處理

錯誤處理始終是編程的難題之一。
什麼是異常

異常是一種對象,其從出錯點被拋出,並被特定類型的異常處理器所捕獲。異常處理就像與程序正常執行路徑並行的、在錯誤發生時執行的另外一條路徑。

異常的處理

異常不能被忽略,它保證必定會在某處獲得處理。異常提供了一種從錯誤狀態進行可靠恢復的途徑。Java一開始就內置了異常處理,並強制你必須使用它。它是惟一可接受的錯誤報告方式。

併發編程

在計算機編程中,存在着在同一時刻處理多個任務的思想。這些彼此獨立運行的部分稱爲線程,同一時刻處理多個任務稱爲併發。

在單一處理器中,線程只是一種爲單一處理器分配執行時間的手段,換而言之,若是隻有一個處理器,那麼多線程程序的運行不過是多個任務競爭使用處理器的性能。在多處理器的狀況下,實現的纔是真正意義上的併發,多處理器並行計算。

多線程同時存在一個隱患,在存在共享資源的時候,可能會形成資源之間的競爭,進而形成死鎖。因此在多線程修改共享資源時,必然在共享資源使用期進行鎖定。

在Java中,JDK1.5後提供了concurrent包支持更好的併發特性。

結語

以上是對象導論的一些基本概念,是繼續閱讀後面章節的非必要補充性材料。對於文中的一些代碼段或概念,暫時不理解的,能夠先放一放,等後面看完了,再回過來看就恍然大悟了。

下一節將講解對象並寫第一個Java程序。若是你對這些內容不感興趣,想看點更高難度的,歡迎關注個人博客:https://www.cnblogs.com/lurke...;歡迎關注個人微信公衆號JavaCorner
JavaCorner內容分享

相關文章
相關標籤/搜索