定義:實現信息隱藏,在java中經過關鍵字private,protected和public實現封裝,利用抽象數據類型將數據和基於數據的操做封裝在一塊兒,使其構成一個不可分割的獨立實體,數據被保護在抽象數據類型的內部,儘量地隱藏內部的細節,只保留一些對外接口使之與外部聯繫。外部對象只能經過已經受權的操做來與這個封裝的對象進行交流和交互。java
好處:良好的封裝可以減小耦合;安全
類內部結構能夠自由修改;this
能夠對成員進行更精確的控制;code
隱藏信息,實現細節;對象
不封裝的時候一個實體類是這麼寫的繼承
public class Husband { public String name ; public int age ; public Wife wife; }
咱們在使用的時候是這麼使用的:接口
public Demo{ public static void mian(String[] args){ Husband husband = new Husband(); husband.age = 30; husband.name = "張三"; } }
問題來了,若是哪一天個人年齡須要的是String類型,那麼此時若是有幾十個上百個類在引用這個實體類,是否是意味着這要修改這幾十個類的年齡爲String,累不累?開發
那麼封裝之後能夠怎麼作的呢,先看看封裝後的這個實體類是怎麼樣的:get
public class Husband { /* * 對屬性的封裝 * 一我的的姓名、年齡、妻子都是這我的的私有屬性 */ private String name ; private int age ; private Wife wife; /* * setter()、getter()是該對象對外開發的接口 */ public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void setWife(Wife wife) { this.wife = wife; } }
如今解決修改年齡爲String的解決辦法只須要修改一處編譯器
public class Husband { /* * 對屬性的封裝 * 一我的的姓名、年齡、妻子都是這我的的私有屬性 */ private String name ; private String age ; private Wife wife; /* * setter()、getter()是該對象對外開發的接口 */ public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(int age) { this.age = String.valueOf(age); } public void setWife(Wife wife) { this.wife = wife; } }
又好比輸入的年齡是1000歲,真把本身當成太子爺(千歲爺)了,這是不符合常識的,這也能夠在這個實體類中進行控制,又好比,咱們存的是0和1顯示的結果是男和女,就能夠在get方法裏面進行控制。
繼承描述的是「is a」的關係,若是有兩個對象A和B若能夠描述爲「A是B」,則能夠表示A繼承B,其中B是被繼承者稱之爲父類或者超類,A是繼承者稱之爲子類或者派生類。
關於繼承必需要說的三個概念:構造器,protected關鍵字,向上轉型
構造器,除了private的方法和屬性之外,父類的構造器也是子類繼承不了的。對於構造器而言,它只可以被調用,而不能被繼承。調用父類的構造方法咱們使用super()便可。
構造器的構建過程是從父類開始向子類一級一級地完成構建。編譯器會默認給子類調用父類的構造器。可是這個調用父類的構造器是有前提的:父類有默認構造器。若是父類沒有默認構造器,咱們就要必須使用super()來調用父類構造器(必須在子類構造器第一行代碼中聲明),不然編譯會報錯。
protected訪問修飾符,在範文範圍中是比private,默認大,比public的修飾符小,同包中能夠訪問,不一樣包的子類亦可訪問。
向上轉型,將子類轉換成父類,在繼承關係上面是向上移動的,因此通常稱之爲向上轉型。因爲向上轉型是由一個叫專用類型向較通用類型轉換,因此它老是安全的,惟一發生變化的可能就是屬性和方法的丟失。
繼承也是存在缺陷的:父類變,子類就必須變;繼承是破壞了封裝,對於父類而言,它的實現細節對於子類來講是徹底透明的;繼承是一種強耦合;
指向子類的父類引用因爲向上轉型了,它只能訪問父類中擁有的方法和屬性,而對於子類中存在而父類中不存在的方法,該引用是不能使用的,儘管是重載該方法。若子類重寫了父類中的某些方法,在調用該些方法的時候,一定是使用子類中定義的這些方法(動態鏈接、動態調用)。實現形式能夠是繼承也能夠是接口,還能夠是內部類
public class Wine { public void fun1(){ System.out.println("Wine 的Fun....."); fun2(); } public void fun2(){ System.out.println("Wine 的Fun2..."); } } public class JNC extends Wine{ /** * @desc 子類重載父類方法 * 父類中不存在該方法,向上轉型後,父類是不能引用該方法的 * @param a * @return void */ public void fun1(String a){ System.out.println("JNC 的 Fun1..."); fun2(); } /** * 子類重寫父類方法 * 指向子類的父類引用調用fun2時,一定是調用該方法 */ public void fun2(){ System.out.println("JNC 的Fun2..."); } } public class Test { public static void main(String[] args) { Wine a = new JNC(); a.fun1(); } } ------------------------------------------------- Output: Wine 的Fun..... JNC 的Fun2...
編譯時多態,指的是方法的重載,這是靜態的重載,而運行時的多態,是經過動態綁定實現的,也就是咱們說的多態。
實現多態必要條件:繼承(實現)、重寫、向上轉型,下面是一個很好體現了繼承的特色的示例,繼承鏈條末端的優先權最高,越往上越低
public class A { public String show(D obj) { return ("A and D"); } public String show(A obj) { return ("A and A"); } } public class B extends A{ public String show(B obj){ return ("B and B"); } public String show(A obj){ return ("B and A"); } } public class C extends B{ } public class D extends B{ } public class Test { public static void main(String[] args) { A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println("1--" + a1.show(b)); System.out.println("2--" + a1.show(c)); System.out.println("3--" + a1.show(d)); System.out.println("4--" + a2.show(b)); System.out.println("5--" + a2.show(c)); System.out.println("6--" + a2.show(d)); System.out.println("7--" + b.show(b)); System.out.println("8--" + b.show(c)); System.out.println("9--" + b.show(d)); } } ---ouput 1--A and A 2--A and A 3--A and D 4--B and A 5--B and A 6--A and D 7--B and B 8--B and A 9--B and A