【轉載】J2SE知識點歸納筆記(三)---Java面向對象 Part 2

注:本文轉載自coder-pig

原文鏈接請戳:http://blog.csdn.net/coder_pig/article/details/22296069



今天雖然是五一假期,但是本人屬於密集恐懼症-陽光恐懼症-社交恐懼症,所以宅在家裏看看書,也是不錯滴選擇,緊接着上篇文章,深入學習下面向對象。可憐加油加油~


Java面向對象 Part 2

前言

在上一節中,我們對面向對象進行了

初步的解析,掌握了類和對象的概念

以及定義,實現,在這一節中,我們將對面向對象的靈魂

繼承與多態進行剖析,同時也會講解下4種內部類的使用

好了,廢話不多說!



繼承:


繼承的理解:

比如:城管,公務員,學生,警察,他們的共性都是人,所以人類是他們的父類,而他們是人類的子類;

子類擁有父類的所有屬性,比如姓名,年齡等,同時子類也衍生了一些自己的特性:比如城管擁有暴力執法的屬性...

呃,這裏說笑而已= =,應該不會給查水錶吧



繼承的方式:

子類  extends  父類  

eg:  class Student extends Person{}


繼承的注意事項:

Java的數據結構:樹形,所以不像C++一樣可繼承多個父類,只能單繼承;Java通過接口和內部類實現多繼承

父類的私有屬性也可以繼承,但是不可以直接進行訪問,只能夠通過父類的方法進行訪問

子類如果想調用父類的構造方法要使用super(參數),否則會提示找不到

Object類是所有類的父類!!



子類構造對象的順序:

先構造父類的對象,再構造子類對象:

遞歸構造父類對象,順序地調用本類成員的賦初值語句,本類的構造方法


繼承代碼示例:

代碼解析:定義一個父類與子類,跟蹤對象的構造順序,同時在子類中調用父類的方法和重寫父類方法


Father.java


  1. package com.jay.example;  
  2.   
  3. public class Father {  
  4.       
  5.       
  6.     //定義兩個私有變量,子類無法直接訪問  
  7.     private String name;  
  8.     private int age;  
  9.       
  10.     //一個好的編程習慣是寫上默認的缺省的構造方法  
  11.       
  12.     //在下面的兩個構造方法中我們都加入一個println語句  
  13.     //以此來跟蹤構造對象的過程  
  14.       
  15.     public Father()  
  16.     {  
  17.         System.out.println("父類無參構造方法被調用");  
  18.     }  
  19.     public Father(String name,int age)  
  20.     {  
  21.         this.name = name;  
  22.         this.age = age;  
  23.         System.out.println("父類的有參構造方法被調用");  
  24.     }  
  25.       
  26.     /*設置這些get和set方法是因爲封裝 
  27.     *我們在子類中想訪問父類的私有元素就只能夠這樣了 
  28.     *通過在父類暴露一個藉口提供給子類訪問 
  29.     */  
  30.     public String getName() {  
  31.         return name;  
  32.     }  
  33.     public void setName(String name) {  
  34.         this.name = name;  
  35.     }  
  36.     public int getAge() {  
  37.         return age;  
  38.     }  
  39.     public void setAge(int age) {  
  40.         this.age = age;  
  41.     }  
  42.       
  43.       
  44.     /* 
  45.      * 這個方法是想在子類中調用的 
  46.      * */  
  47.       
  48.     public void printMessage()  
  49.     {  
  50.         System.out.println(name + "今年" + age + "歲");  
  51.     }  
  52.       
  53.     /* 
  54.      * 這個方法是供子類覆蓋重寫的 
  55.      * */  
  56.     public void test()  
  57.     {  
  58.         System.out.println("我是父類的test");  
  59.     }  
  60.       
  61. }  


Son.java


  1. package com.jay.example;  
  2.   
  3. public class Son extends Father{  
  4.     //定義子類自己的屬性  
  5.     private int grade;  
  6.       
  7.     /* 
  8.      * 同理,爲兩個構造方法添加println語句用於跟蹤構造對象的順序 
  9.      * */  
  10.     Son(){        
  11.         System.out.println("子類的無參構造方法被調用了");  
  12.     }  
  13.       
  14.     Son(String name,int age,int grade){  
  15.         //通過super關鍵字調用父類的構造方法,進行參數傳遞  
  16.         super(name,age);  
  17.         this.grade = grade;  
  18.         System.out.println("子類的有參構造方法被調用了");  
  19.     }  
  20.   
  21.       
  22.     public int getGrade() {  
  23.         return grade;  
  24.     }  
  25.   
  26.     public void setGrade(int grade) {  
  27.         this.grade = grade;  
  28.     }  
  29.       
  30.     //調用父類的方法訪問父類的私有變量  
  31.     public void printMsg()  
  32.     {  
  33.         System.out.println(getName()+"小學生今年"+getAge()+"歲,讀"+ grade + "年級");  
  34.     }  
  35.       
  36.     //重寫父類的test方法  
  37.     public void test()  
  38.     {  
  39.         System.out.println("我是子類的test");  
  40.     }  
  41. }  


ExtendTest.java


  1. package com.jay.example;  
  2.   
  3. public class ExtendTest {  
  4.       
  5.     public static void main(String[] args) {  
  6.           
  7.         Son son1 = new Son();  
  8.         son1.setName("大豬");  
  9.         son1.setAge(25);  
  10.         son1.printMessage();  
  11.           
  12.         System.out.println();  
  13.           
  14.         Son son2 = new Son("小豬",20,1);  
  15.         son2.printMsg();  
  16.           
  17.         System.out.println();  
  18.         son2.test();  
  19.     }  
  20.       
  21. }  


輸出結果:



結果分析:

①從上面我們可以知道"先有父親,後又兒子";創建子類對象時會先創建一個父類對象,

不用我們自己實例化父類對象,系統自動創建;

②我們可以通過super()訪問父類構造方法或者用super.XXX訪問父類的同名成員

③子類可以重寫父類中的方法成員



super關鍵字:

子類中訪問父類的同名成員,用super語句向父類構造方法傳,那麼super(參數)方法要放在第一句 





多態:


多態的分類:


 編譯時多態(方法重載)  OverLoading


在同一個類中可以定義多個同名的方法,各個方法的參數表一定不同(參數個數,類型)

返回值可以不同;比如構造方法的重載就是編譯時的多態了


代碼示例:


  1. package com.jay.example;  
  2.   
  3. class HeHe  
  4. {  
  5.     public HeHe(){}  
  6.       
  7.     //這裏重寫幾個一樣的show方法  
  8.     public void show()  
  9.     {  
  10.         System.out.println("①重寫");  
  11.     }     
  12.     public void show(int a)  
  13.     {  
  14.         System.out.println("②重寫");  
  15.     }     
  16.     public void show(float a)  
  17.     {  
  18.         System.out.println("③重寫");  
  19.     }  
  20.     public void show(int a,float b)  
  21.     {  
  22.         System.out.println("④重寫");  
  23.     }  
  24. }  
  25.   
  26.   
  27. public class OverLoadingTest  
  28. {  
  29.     public static void main(String[] args) {  
  30.         HeHe he = new HeHe();  
  31.         he.show();  
  32.         he.show(1);  
  33.         he.show(0.1f);  
  34.         he.show(20.2f);  
  35.     }  
  36. }  


運行結果:





運行時多態:(方法重定義/覆蓋)    OverRidding


運行時多態 = 繼承  +  重定義  + 動態綁定


方法覆蓋:

子類方法與父類方法名,參數相同,返回值類型也相同;

規律:不能迴避比父類方法更多的異常,子類訪問控制必須必父類方法更公開


向上轉型規則(upcasting)

Animal a = new dog();

Dog  d = (Dog)a;


這裏有個問題:

如果調用a的叫方法,jiao()那麼,調用的會是Animal的叫還是Dog的叫?

答案是:狗叫,new後面是什麼類,動態類型就是什麼類

不懂沒關係,看下面的演示代碼


  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 代碼解析: 
  5.  * 在代碼中我們定義了三個類,父類,子類以及一個測試類 
  6.  * 我們要驗證的是Father f = new Son(123);當我們調用相同名稱的方法時 
  7.  * 是以父類的方法還是以子類的方法爲準 
  8.  * 從代碼可知,我們對print方法進行了重載 
  9.  * */  
  10.   
  11.   
  12. class Father {  
  13.     public Father() {  
  14.         System.out.println("父類構造方法打印前\t");  
  15.         print();  
  16.         System.out.println("父類構造方法打印後\t");  
  17.     }  
  18.       
  19.     public void print()  
  20.     {  
  21.         System.out.println("父類的打印方法\t");  
  22.     }  
  23. }  
  24.   
  25. class Son extends Father{  
  26.     int flag;  
  27.     public Son(int flag) {  
  28.         this.flag = flag;  
  29.         System.out.println("子類的構造方法\t"this.flag);  
  30.     }  
  31.       
  32.     public void print()  
  33.     {  
  34.         System.out.println("子類打印方法\t" + flag);  
  35.     }  
  36. }  
  37.   
  38.   
  39. public class OverRridingTest  
  40. {  
  41.     public static void main(String[] args) {  
  42.           
  43.         Father f = new Son(123);  
  44.     }  
  45. }  


運行結果:




分析總結:

從上面的代碼,相信大家對運行時的多態有更深一步的瞭解了;

第二行輸出 0 ,說明了調用的是子類的print,這也說明了new後面什麼類型,動態類型就是什麼類型






內部類:

內部類有:成員內部類,靜態內部類,局部內部類,匿名內部類四種


成員內部類:

將一個類嵌套定義在另一個類中,包含內部類的類叫做外部類

內部類可以直接訪問外部類的成員和方法

注意:訪問內部類的話需要先創建外部類對象,接着纔可以用它來創建內部類對象


代碼示例:

  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 該代碼演示瞭如何訪問內部類,有以下兩種方式 
  5.  * ①在外部類中直接實例化內部類,並且調用內部類的方法或者參數 
  6.  * ②在測試類中先實例化外部類,在實例化內部類,從而調用對應的方法 
  7.  * eg:注意是這樣寫哦!Outer.Inner iner = out1.new Inner(); 
  8.  * */  
  9.   
  10.   
  11. class Outer  
  12. {  
  13.     String outString = "外部類的成員變量被訪問";  
  14.     //在該方法中實例化內部類,並且調用show方法  
  15.     void showinner()  
  16.     {  
  17.         Inner in = new Inner();  
  18.         in.show();  
  19.     }  
  20.       
  21.     //創建一個成員內部類  
  22.     class Inner  
  23.     {  
  24.         void show()  
  25.         {  
  26.             System.out.println("內部類的show方法被調用!");  
  27.             System.out.println(outString);  
  28.         }  
  29.         //用於演示在其他類中使用內部類的方法  
  30.         void test()  
  31.         {  
  32.             System.out.println("在測試類中訪問內部類的方法");  
  33.         }  
  34.     }  
  35. }  
  36.   
  37.   
  38.   
  39. public class InnerTest {  
  40.   
  41.     public static void main(String[] args) {  
  42.           
  43.         Outer out1 = new Outer();  
  44.         out1.showinner();  
  45.         //直接實例化內部類,注意寫法!  
  46.         //如果寫成Outer.Inner iner = new Outer.Inner();是錯的哦!  
  47.         Outer.Inner iner = out1.new Inner();  
  48.         iner.test();  
  49.           
  50.     }  
  51. }  

運行結果:



靜態內部類:

是成員內部類的一種,但又是特殊的,他具有以下特性:

靜態內部類只能夠訪問外部類的靜態成員;

創建內部類對象不需要外部對象,直接:new 外部類名.內部類的構造方法


代碼示例:

  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 該代碼演示了靜態內部類的使用 
  5.  * 內部類對象只能夠訪問外部類對象中的靜態成員 
  6.  * 如果調用非靜態成員會報錯 
  7.  * 也演示了兩種實例化靜態內部類成員的辦法 
  8.  * 直接new 外部類.內部類即可 
  9.  * */  
  10.   
  11.   
  12. class Draw  
  13. {     
  14.           
  15.     public static int k = 250;  
  16.     public void print()  
  17.     {  
  18.         Pen p = new Pen("豬頭");  
  19.         p.speak();  
  20.     }  
  21.       
  22.       
  23.     static class Pen  
  24.     {  
  25.         int i = 100;  
  26.         String name ;  
  27.           
  28.         public Pen(String name)   
  29.         {  
  30.             this.name = name;  
  31.         }  
  32.           
  33.         void speak()  
  34.         {  
  35.             System.out.println(name + "你好!\t"+k);  
  36.         }  
  37.     }  
  38. }  
  39.   
  40.   
  41. public class StaticTest {  
  42.     public static void main(String[] args)   
  43.     {  
  44.           
  45.         Draw d = new Draw();  
  46.         d.print();  
  47.           
  48.         Draw.Pen pen= new Draw.Pen("呵呵");  
  49.         pen.speak();  
  50.     }  
  51. }  

運行截圖:




局部內部類:

與成員內部類不同,局部內部類是存在於類中的某個局部,可能是在某個方法或者某個塊語句中

是用的最少的一種內部類,和局部變量一樣,不能夠被public,protected,private和static修飾

只能夠訪問方法中定義的final類型的局部變量

只能夠在方法中生成局部內部類的對象並且調用它的方法


實例代碼:

  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 該代碼演示的是 
  5.  * 在外部類的方法中創建一個局部內部類 
  6.  * 同時需要在方法中實例化這個內部類對象 
  7.  * 而內部類可以訪問外部類成員和方法中final修飾的成員變量 
  8.  * */  
  9.   
  10. class Outer  
  11. {  
  12.     int a = 1;  
  13.       
  14.     public void show()  
  15.     {  
  16.         int b = 2;  
  17.         final int c = 3;  
  18.         //定義一個局部內部類  
  19.         class Inner  
  20.         {  
  21.             public void inPrint()  
  22.             {  
  23.                 System.out.println("局部內部類的方法:");  
  24.                 //可以訪問外部類中的變量  
  25.                 System.out.println(a);  
  26.                   
  27.                 //system.out.printf(b);這裏可是會報錯的哦!  
  28.                   
  29.                 //可以訪問方法中的final的變量  
  30.                 System.out.println(c);  
  31.             }  
  32.         }  
  33.           
  34.         //需要在方法中實例化內部類對象哦!  
  35.         new Inner().inPrint();  
  36.     }  
  37.   
  38. }  
  39.   
  40.   
  41.   
  42. public class LoaclTest {  
  43.     public static void main(String[] args) {  
  44.         //創建外部類對象,同時調用外部類的方法  
  45.         Outer out = new Outer();  
  46.         out.show();  
  47.     }  
  48. }  


匿名內部類:

沒有名稱的內部類,必須是非靜態的類

通常是隱式地繼承一個父類或者實現一個接口

用的比較多的是作爲某個方法的參數,如Java中的GUI事件編程,android中事件處理機制

比較簡單,看下下面android中爲按鈕設置點擊事件的方法就瞭解了


  1. btnregister.setOnClickListener(new OnClickListener() {  
  2.               
  3.             @Override  
  4.             public void onClick(View arg0) {  
  5.                 Intent it = new Intent(LoginActivity.this,RegisterActivity.class);  
  6.                 startActivityForResult(it, 0x123);  
  7.                 overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);  
  8.             }  
  9.         });  

代碼解析:

代碼實現了爲按鈕設置一個點擊事件,參數,直接是通過new OnClickListener(){}這裏實例化一個匿名內部類對象

作爲參數,並且重寫OnClickListerner接口中的onClick()方法




總結:

在這一節中,我們深入面向對象,學習了面向對象的核心部分

繼承與多態,並且瞭解了四種內部類的使用

內容不多,讀者寫相關代碼體現其中的奧祕!


好的,最後謝謝各位讀者的支持

如果有什麼紕漏,錯誤,不好的,或者什麼好的建議;

望讀者指出,不甚感激,(*^__^*) 嘻嘻……!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章