Java中有三大特性,分別是封裝繼承多態,其理念十分抽象,並且是層層深入式的. 一.封裝 概念:封裝,即隱藏對象的屬性和實現細節,僅對外公開介面,控制在程式中屬性的讀和修改的訪問級別;將抽象得到的數據和行為(或功能)相結合,形成一個有機的整體,也就是將數據與操作數據的源代碼進行有機的結合,形成“類” ...
Java中有三大特性,分別是封裝繼承多態,其理念十分抽象,並且是層層深入式的.
一.封裝
概念:封裝,即隱藏對象的屬性和實現細節,僅對外公開介面,控制在程式中屬性的讀和修改的訪問級別;將抽象得到的數據和行為(或功能)相結合,形成一個有機的整體,也就是將數據與操作數據的源代碼進行有機的結合,形成“類”,其中數據和函數都是類的成員。在電子方面,封裝是指把矽片上的電路管腳,用導線接引到外部接頭處,以便與其它器件連接。(來自百度)
在將成員屬性封裝之後,我們應該提供相應的get/set方法進行訪問此成員屬性.
封裝的好處是:屬性進行了隱藏,不再是暴露在外的數據,使數據更加的安全可靠.
1 class A{ 2 private int a;//此變數進行了封裝 3 //提供給外部訪問的介面,實現了只讀和只寫 4 public int getA(){ 5 return a; 6 } 7 public void setA(int a){ 8 this.a=a; 9 } 10 }
提到封裝就必須要提到private關鍵字,如上代碼,private是一個許可權修飾符,它可以將成員方法和成員屬性私有化,使其只有類內部能夠訪問到.
許可權修飾符有4種,分別是public->protected->default->private 其中private許可權最嚴格
public:可以在全工程訪問到 protected:只有這個類的子類可以訪問 defaule:為預設,無須寫出,類所在包下可以訪問 private:僅僅只有本省類可以訪問
提到了封裝就不得不提到this關鍵字
概念:this關鍵字指這個當前對象的引用
this關鍵字有三種用法:
1.this.成員方法,這種方法用於給成員變數的賦值.
1 class A{ 2 private int a;//此變數進行了封裝 3 //提供給外部訪問的介面,實現了只讀和只寫 4 public int getA(){ 5 return a; 6 } 7 public void setA(int a){ 8 this.a=a; 9 } 10 }
因為就近原則,所以直接a=a;實際上並沒有對成員屬性進行賦值,所以需要使用this關鍵字對其進行訪問.
2.調用構造方法,如:可以在空參構造方法中調用有參構造方法
1 class A{ 2 private int a;//此變數進行了封裝 3 //提供給外部訪問的介面,實現了只讀和只寫 4 public int getA(){ 5 return a; 6 } 7 public void setA(int a){ 8 this.a=a; 9 } 10 //空參構造 11 public A(){ 12 this(1); 13 } 14 //全參構造 15 public A(int a){ 16 this.a=a; 17 } 18 }
這個例子使用this在空參構造中調用了全參構造
使用this調用構造方法時需要註意:
1.this()必須在構造方法中的第一行,且只能夠使用一次
2.this()不能夠互相調用,因為會陷入死迴圈,如下:
1 class A{ 2 private int a;//此變數進行了封裝 3 //提供給外部訪問的介面,實現了只讀和只寫 4 public int getA(){ 5 return a; 6 } 7 public void setA(int a){ 8 this.a=a; 9 } 10 //空參構造 11 public A(){ 12 this(1); 13 //this();錯誤 14 } 15 //全參構造 16 public A(int a){ 17 //this();錯誤 18 this.a=a; 19 } 20 }
3.this可以當作返回值使用,this是當前對象的引用,所以返回的同樣是一個A類型,可以使用一個新的A類型對象b進行接受,b會繼承所有a的屬性值,使用方法如下:
class A{ private int a;//此變數進行了封裝 //提供給外部訪問的介面,實現了只讀和只寫 public int getA(){ return a; } public void setA(int a){ this.a=a; } //使用this當作返回值 A b(){ return this; } //空參構造 public A(){ this(1); } //全參構造 public A(int a){ this.a=a; } }
二.繼承
概念:繼承即從已有的類中派生一個新的類,已有的類成為父類(基類,超類),而派生的類成為子類(派生類).若類B繼承了類A,則我們把類A稱為類B的子類,反之同理,子類可以擁有自己本身的特有方法以及特有屬性,而父類則必須是子類的共性抽取.如動物都有顏色,年齡,其顏色和年齡就是其共性
1 class A{ 2 int a; 3 void a(){} 4 } 5 class B extends A{ 6 //子類特有方法 7 void b(){ 8 } 9 }
1. 繼承需要註意的點
(1)繼承是類在繼承,而不是對象在繼承
(2)子類無條件繼承父類的所有成員屬性及成員方法
(3)若方法出現重寫,屬性出現重覆,則優先使用子類的方法和屬性(就近原則).
(4)繼承不繼承父類的構造方法
2.java中繼承的特點
(1).java不支持多繼承,但是可以通過介面實現多繼承 多繼承,即子類繼承自多個父類
(2).java支持多重繼承 多重繼承,即子類繼承父類,父類繼承他的父類,即子類相當於其孫子輩
class A{ int a; public A(){ //super();這裡有一個預設的super()方法 } public A(int a){ //super();這裡有一個預設的super()方法 } void a(){} } class B extends A{ //子類的特有屬性 int b; //子類特有方法 void b(){ //調用父類的成員屬性 System.out.println(super.a); //調用父類的成員方法 super.a(); } public B(){
//調用父類的有參構造 super(1); } }
提到繼承就必須提到super關鍵字,super關鍵字指父類的引用,super關鍵字最重要的是每個類的構造方法都有其預設的一個super()方法,我們知道所有的類都是繼承自Object類,而super()這個方法其實是調用到Object處進行空間的申請.
super關鍵字的使用
1.訪問父類成員方法和成員屬性 super.成員方法() super.成員屬性
2.訪問父類的構造方法 super(參數)
1 abstract class Animal{ 2 private String color; 3 private int numOfLegs; 4 abstract void eat(); 5 public String getColor() { 6 return color; 7 } 8 public void setColor(String color) { 9 this.color = color; 10 } 11 public int getNumOfLegs() { 12 return numOfLegs; 13 } 14 public void setNumOfLegs(int numOfLegs) { 15 this.numOfLegs = numOfLegs; 16 } 17 public Animal(String color, int numOfLegs) { 18 super(); 19 this.color = color; 20 this.numOfLegs = numOfLegs; 21 } 22 public Animal() { 23 super(); 24 } 25 26 } 27 class Dog extends Animal{ 28 Dog(){ 29 super(); 30 } 31 Dog(String color,int numOfLegs){ 32 super(color,numOfLegs); 33 } 34 @Override 35 void eat(){ 36 System.out.println(super.getNumOfLegs()+"條腿"+super.getColor()+"的狗在啃骨頭"); 37 } 38 void lookHome(){ 39 System.out.println(super.getNumOfLegs()+"條腿"+super.getColor()+"的狗在看家"); 40 } 41 } 42 class Porrot extends Animal{ 43 Porrot(){ 44 super(); 45 } 46 Porrot(String color,int numOfLegs){ 47 super(color,numOfLegs); 48 } 49 @Override 50 void eat(){ 51 System.out.println(super.getNumOfLegs()+"條腿的"+super.getColor()+"鸚鵡在吃小米"); 52 } 53 void say(){ 54 System.out.println(super.getNumOfLegs()+"條腿的"+super.getColor()+"鸚鵡在說你好,醜八怪"); 55 } 56 }
提到繼承當然也不能不提到抽象類,定義一個抽象類使用是這樣的:public abstract class Animal(){}
當你想要創建一個動物類時,你知道動物都會吃,但是你不知道動物的子類吃是如何具體實現的,如:貓吃魚,但是狗吃的是骨頭同樣的子類,但是其方法的實現卻是不同的,這個時候就需要使用抽象類了.
抽象類的註意點:
1.抽象類必須在類中使用abstract關鍵字進行修飾,
2.抽象類中可以沒有抽象方法,
3.抽象類不能夠實例化,如果想要實例化的話則需要子類將其所有的抽象方法重寫
1 interface A{ 2 int b=0;//預設有public static final; 3 void a(){}//預設有public abstract; 4 } 5 interface B{ 6 } 7 class Father{ 8 } 9 class Son extends Father implements A,B{ 10 //方法的實現 11 public void a(){ 12 } 13 }
提到抽象類就一定要提到介面
介面:介面其實相當於一個規範,當你定義一個介面時,實現介面的類必須實現介面中的所有的方法.舉個現實中的例子,比如我們的手機充電藉口,基本很少發生改變,因為他已經是規定死了的,使用介面等於制定一個規範,等於是所有的實現此介面的類都必須實現此規範,這樣就可以用介面來實現不同類的比較等操作.
介面的註意點:
1.介面中的成員屬性必須都是public static final的,不修飾會自動加上,介面中的成員方法必須都是public static修飾的,且不可以使用其他的許可權修飾符
2.介面不可以被實例化,必須使用子類 explements 介面,然後實現介面中的方法.
3.一個類可以實現多個介面,可以在實現抽象類的同時實現多個介面或單個介面
三.多態
概念:同一個行為,對於傳入不同的對象,實現不同的動作 多態需要記住的一個概念:父類引用指向子類對象
多態的好處:提高了代碼的可復用性.
多態的壞處:無法使用子類所特有的方法.因為編譯時看的是右邊.
多態的實現必須有三要素 1.繼承(實現) 2.重寫 3.向上轉型(缺一不可!!!)
1 public class Test{ 2 public static void main(String[] args){ 3 show(new Dog()); 4 show(new Cat()); 5 } 6 public static void show(Animal a){ 7 a.eat(); 8 } 9 } 10 abstract class Animal{ 11 abstract void eat(){ 12 } 13 } 14 class Dog extends Animal{ 15 public void eat(){ 16 System.out.println("在吃骨頭"); 17 } 18 } 19 class Cat extends Animal{ 20 public void eat(){ 21 System.out.println("在吃魚"); 22 } 23 }
多態基於繼承的實現如上.
public class Test01{ public static void main(String[] args){ show(new Dog()); show(new Cat()); } public static void show(Animal a){ a.eat(); } } interface Animal{ abstract void eat(); } class Dog implements Animal{ public void eat(){ System.out.println("在吃骨頭"); } } class Cat implements Animal{ public void eat(){ System.out.println("在吃魚"); } }
介面的實現如上
提到多態就需要提到一個例子:
public class Test01{ 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(); a1.show(b);// a and a a1.show(c);//a and a a1.show(d);//a and d a2.show(b);//b and a a2.show(c);//b and a a2.show(d);//a and d } /*public static void show(Animal a){ a.eat(); }*/ } class A{ void show(A a){ System.out.println("a and a"); } void show(D d){ System.out.println("a and d"); } } class B extends A{ void show(A a){ System.out.println("b and a"); } void show(B b){ System.out.println("b and b"); } } class C extends B{ } class D extends C{ }
我們先看a2.show(c),首先a2是一個a類型的引用類型,在a2種尋找show(c)參數為c類型的方法,沒有找到c類型的方法,於是到a2的超類尋找其方法,由於a類的超類是Object,也並沒有show(c)這個方法,於是將c類型進行了提升,變成了b類型,b類型在a中也不存在,於是便轉換成了a類型,a類型與A類中找到了方法,並由於A類型的show方法於B類型中進行了重寫,於是便輸出了b and a
其尋找的順序是:this.show(O) super.show(O) this.show(super(O)) super.show(super(O))
當使用了上述方法進行了多態的實現之後,其子類就會自動將其的特有方法給丟棄掉了,然而我們現在想調用這個對象的特有方法怎麼辦?
答案是使用使用強制類型轉換,而使用強制類型轉換則會有可能出現類型轉換異常,這個時候就需要使用instanceof運算符,使用方法:父類對象 instanceof 子類,若父類引用時子類類型時返回true,則可以使用強制類型轉換
這種實現過程叫做向下轉型