咱們程序設計追求「高內聚,低耦合」java
高內聚:類的內部數據操做細節本身完成,不容許外部干涉面試
低耦合:僅對外暴露少許的方法用於使用。數據庫
隱藏對象內部的複雜性,只對外公開簡單的接口。便於外界調用,從而提升系統的可擴展性、可維護性。通俗的說,把該隱藏的隱藏起來,該暴露的暴露岀來。這就是封裝性的設計思想。this
當咱們建立一個類的對象之後,咱們能夠經過"對象.屬性"的方式,對對象的屬性進行賦值。這裏,賦值操做要受到屬性的數據類型和存儲範圍的制約。除此以外,沒其餘制約條件。可是,在實際問題中,咱們每每須要給屬性賦值加入額外的限制條件。這個條件就不能在屬性聲明時體現,咱們只能經過方法進行限制條件的添加。(好比:setLegs()同時,咱們須要避免用戶再使用"對象.屬性"的方式對屬性進行賦值。則須要將屬性聲明爲私有的(private).spa
此時,針對於屬性就體現了封裝性。設計
體現一:code
將類的屬性xxx私化(private),同時,提供公共的(public)方法來獲取(getXxx)和設置(setXxx)此屬性的值對象
private double radius; public void setRadius(double radius){ this.radius = radius; } public double getRadius(){ return radius; }
體現二:不對外暴露的私有的方法繼承
體現三:單例模式(將構造器私有化)接口
體現四:若是不但願類在包外被調用,能夠將類設置爲缺省的。
經過對不一樣的方法屬性設置不一樣的權限修飾符來達到對類進行封裝的目的。
4.1 權限從小到大順序爲:private < 缺省 < protected < public
4.2 具體的修飾範圍:
修飾符 | 類內部 | 同一個包 | 不一樣包的子類 | 同一個工程 |
---|---|---|---|---|
private | Yes | |||
(缺省) | Yes | Yes | ||
protected | Yes | Yes | Yes | |
public | Yes | Yes | Yes | Yes |
4.3 權限修飾符可用來修飾的結構說明:
4種權限均可以用來修飾類的內部結構:屬性、方法、構造器、內部類
修飾類的話,只能使用:缺省、public
class A extends B{} * A:子類、派生類、subclass * B:父類、超類、基類、superclass
判斷是否要進行繼承:A is a B,若成立,則B繼承A
3.1體現:一旦子類A繼承父類B之後,子類A中就獲取了父類B中聲明的全部的屬性和方法。
特別的,父類中聲明爲private的屬性或方法,子類繼承父類之後,仍然認爲獲取了父類中私的結構。只由於封裝性的影響,使得子類不能直接調用父類的結構而已。
3.2 子類繼承父類之後,還能夠聲明本身特有的屬性或方法:實現功能的拓展。
子類和父類的關係,不一樣於子集和集合的關係。
extends:延展、擴展
是Java中全部類的父類,相似於二叉樹中的根節點,定義了一些通用的方法。
方法名 | 類型 | 描述 |
---|---|---|
public Object() | 構造方法 | 構造器 |
public boolean equals( Object obj) | 普通方法 | 對象比較 |
public int hashCode() | 普通方法 | 獲取Hash碼 |
public String toString() | 普通方法 | 對象打印時調用 |
能夠理解爲一個事物的多種形態。好比數據庫的鏈接方式,咱們定義好了數據庫的鏈接,也規定了鏈接時的步驟,可是咱們並不知道用戶會採用什麼數據庫,在沒有多態之前咱們只能針對不一樣的數據庫寫不一樣的鏈接方法,而有了多態之後咱們只須要定義好數據庫的類並書寫好鏈接方法,讓全部的數據庫繼承數據庫類並重寫數據庫鏈接方法。這樣咱們在調用的時候只須要經過聲明數據庫類並指向數據庫的子類的方式,*(即數據庫類的引用指向繼承了數據庫類的具體實現類的對象)*就能夠進行數據庫鏈接。而不是須要針對不一樣的數據庫書寫不一樣的鏈接方式。
對象的多態性:父類的引用指向子類的對象(或子類的對象賦給父類的引用)
編譯時和運行時類型不一致,產生了多態
舉例:
Person p = new Man(); Object obj = new Date();
有了對象的多態性之後,咱們在編譯期,只能調用父類中聲明的方法,但在運行期,咱們實際執行的是子類重寫父類的方法。
總結:編譯,看左邊;運行,看右邊。
對象的多態:在Java中,子類的對象能夠替代父類的對象使用
① 類的繼承關係 ② 方法的重寫
舉例一: public void func(Animal animal){//Animal animal = new Dog(); animal.eat(); animal.shout(); } 舉例二: public void method(Object obj){ } 舉例三: class Driver{ public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection(); //規範的步驟去操做數據 // conn.method1(); // conn.method2(); // conn.method3(); } }
對象的多態性,只適用於方法,不適用於屬性(編譯和運行都看左邊)
個引用類型變量若是聲明爲父類的類型,但實際引用的是子類對象,那麼該變量就不能再訪問子類中添加的屬性和方法
小結: 多態的做用:提升了代碼的通用性,常稱做接口重用 前提: 須要存在繼承或者實現關係 有方法的重寫 成員方法: 編譯時:要查看引用變量所聲明的類中是否有所調用的方法 運行時:調用實際new的對象所屬的類中的重寫方法 成員變量: 不具有多態性,只看引用變量所聲明的類
有了對象的多態性之後,內存中其實是加載了子類特有的屬性和方法的,可是因爲變量聲明爲父類類型,致使編譯時,只能調用父類中聲明的屬性和方法。子類特有的屬性和方法不能調用。如何才能調用子類特的屬性和方法?使用向下轉型。
使用強制類型轉換符:()
Person p = new Man(); Man m1=(Man)p2;//向下轉型
① 使用強轉時,可能出現ClassCastException的異常。 ② 爲了不在向下轉型時出現ClassCastException的異常,咱們在向下轉型以前,先進行instanceof的判斷,一旦返回true,就進行向下轉型。若是返回false,不進行向下轉型。
只有對象A是B的子類實例化對象或者在下層的子類,才能向下轉型
① a instanceof A :判斷對象a是不是類A的實例。若是是,返回true;若是不是,返回false。
② 若是 a instanceof A返回true,則 a instanceof B也返回true.其中,類B是類A的父類。
③ 要求a所屬的類與類A必須是子類和父類的關係,不然編譯錯誤。
p instanceif Man//左邊是變量名,右邊是類的類型
運行時行爲
class Base { int count = 10; public void display() { System.out.println(this.count); } } class Sub extends Base { int count = 20; public void display() { System.out.println(this.count); } } public class FieldMethodTest { public static void main(String[] args) { Sub s = new Sub(); System.out.println(s.count);//20 s.display();//20 Base b = s;//多態性 //==:對於引用數據類型來說,比較的是兩個引用數據類型變量的地址值是否相同 System.out.println(b == s);//true System.out.println(b.count);//10 b.display();//20 } }
強調: