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

注:本文轉載自coder-pig

原文請戳:http://blog.csdn.net/coder_pig/article/details/22667533


總體來說小豬的文章寫的挺詳細,這個傢伙挺有耐心的,稍安勿躁,一步步來~吐舌頭



Java面向對象   Part  3


前言


在前面的兩節中我們對面向對象已經有了差不多的瞭解了,

而這一節也是Java面向對象部分的一個結尾,

在這一節中我們會對抽象類,接口,修飾符,枚舉,封裝進行解析;





抽象類


什麼是抽象類?

我們將具有共同特點的類進行抽象後得到的一個類,而這個類本身的方法並沒有任何具體的實現;

eg:定義一個抽象的動物類,然後定義幾個抽象方法(動物共有的方法),比如設置有多少隻腳的方法

      public abstract void setFoods();


抽象類的定義:

一般使用abstract關鍵字修飾  

抽象類:      修飾符  abstract    類名{//類的內容} 

抽象方法:    修飾符  abstract   返回值類型  方法名();


抽象類的使用規則:

①如果一個類有一個抽象方法,那麼這個類一定是抽象類;反之,如果一個類是抽象類,但可能包含有非抽象的方法

②如果一個類繼承了一個抽象類,那麼必須重寫抽象類中所有的抽象方法,是所有!所有!如果沒有全部實現的話

    那麼子類必須也要定義爲一個抽象類

③abstract不能和static放在一起,否則會出現錯誤(因爲static不能被覆蓋,abstract爲了生效,必須被覆蓋)

④抽象類可不能定義爲最終哦!abstract不能與final共存!

⑤注意區分方法的空實現和方法的抽象

eg:方法的空實現:private void show(){}            方法的抽象,無實現: private void show();

⑥抽象類不能夠實例化哦!但是可以new的時候重寫裏面的抽象方法



抽象類使用實例

代碼:

  1. package com.jay.example;  
  2.   
  3.   
  4.   
  5. /* 
  6.  * 該代碼是定義一個抽象類,汽車類,定義幾個屬性和抽象方法 
  7.  * 然後定義客車,吊車類作爲它的子類, 
  8.  * 在客車類中即重寫抽象方法,也重寫了具體方法 
  9.  * 在吊車類中,只是重寫具體方法,不重寫抽象方法,所以吊車類 
  10.  * 需要被設置爲抽象類,否則會報錯 
  11.  * */  
  12.   
  13.   
  14. abstract class Car  
  15. {  
  16.     protected String color;  
  17.     protected int sudu;  
  18.       
  19.     //定義一個具體的方法  
  20.     public void speed()  
  21.     {  
  22.         System.out.println("加速");  
  23.     }     
  24.     //定義一個抽象方法,是方法的空實現哦,子類繼承時需要覆蓋該方法  
  25.     public abstract void useful();  
  26. }  
  27.   
  28. class Truck extends Car  
  29. {     
  30.     public void speed()  
  31.     {  
  32.         System.out.println("卡車起步很慢");  
  33.     }  
  34.     public void useful() {  
  35.         System.out.println("卡車是用於貨運的!");  
  36.     }  
  37.       
  38. }  
  39.   
  40.   
  41. //定義吊車類,沒有實現抽象方法,所以需爲抽象類  
  42. abstract class Crane extends Car  
  43. {  
  44.     public void speed() {  
  45.         System.out.println("吊車走得更加慢!");  
  46.     }  
  47. }  
  48.   
  49.   
  50. public class AbstractDemo {  
  51.     //抽象類可不能直接實例化哦!Car c = new Car()是會報錯的  
  52.     //當然可以通過向上轉型的規則:Car c = new Track();是可以的  
  53.     public static void main(String[] args) {  
  54.         Truck tr = new Truck();  
  55.         tr.speed();  
  56.         tr.useful();  
  57.         //下面是演示protected修飾的作用於,子類或者同包可見  
  58.         tr.color = "白色";  
  59.         tr.sudu = 40;  
  60.         System.out.println(tr.color + tr.sudu + "km/h");  
  61.     }  
  62.       
  63. }  


運行截圖:



代碼解析:

該代碼演示了抽象類的基本用法,定義抽象類父類Car,定義了一個抽象方法和具體方法

然後在卡車類中都重寫了兩個方法;在吊車類中僅僅重寫了具體方法,所以吊車類需要被設置爲抽象類

最後還演示了protected的作用域:子類與同包可見



接口


接口的介紹:

因爲Java的數據結構是樹型的,所以不像C++那樣可以同時繼承多個父類;但是Java通過接口和內部類實現了多繼承

接口是一種特殊的抽象類,一個類實現一個接口,相當於它繼承了一個抽象類


接口的定義:

修飾符  inteface 接口名{"內容"}


接口的實現:

一個類可以在繼承一個父類同時實現多個接口,用","分隔

class 類名  extents  父類  implements 接口1,接口2...{}


使用規則:

①一個Java文件中只允許有一個public修飾的類或者接口,且需與文件名同名,是一個!!

②在一個接口中,所有方法都是公開的,抽象的方法!!所有的屬性都是公開,靜態,常量!

③如果一個類聲明實現一個接口,但是沒有實現接口中的所有方法,那麼這個類必須是抽象類哦!

④接口只關心功能,並不關心功能的具體實現

⑤接口也可以通過extends繼承哦!但是依舊需要實現子接口和父接口中的所有抽象方法

⑥接口中的方法可以不寫public,但是子類實現接口中的抽象方法時,要寫上public,不然會報錯哦!


代碼示例:


  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 在這個代碼中,我們定義了兩個父接口,又用一個子接口對兩個父接口進行了繼承 
  5.  * 同時爲子接口又定義了一個抽象方法;然後定義了一個Person實現兩個父接口 
  6.  * 重寫了兩個抽象方法;又定義了一個Worker實現了子接口,但同時也需要把父接口 
  7.  * 中的抽象方法進行覆蓋 
  8.  *  
  9.  * */  
  10.   
  11.   
  12. //定義一個說話的接口  
  13. interface Speak  
  14. {  
  15.     void speak();  
  16. }  
  17.   
  18. //定義一個吃飯的接口  
  19. interface Eat  
  20. {  
  21.     void eat();  
  22. }  
  23.   
  24. //定義一個子接口,同時繼承說話和吃飯的接口,同時定義一個走路的方法  
  25. interface Walk extends Speak,Eat  
  26. {  
  27.     void walk();  
  28. }  
  29.   
  30. //定義一個Person類,實現說話和吃飯接口,重寫接口中的抽象方法  
  31. //子類在實現接口的時候,public修飾符不可以省略,不然會報錯  
  32. class Person implements Speak,Eat  
  33. {  
  34.     public void speak()  
  35.     {  
  36.         System.out.println("Person類可以說話");  
  37.     }  
  38.     public void eat()  
  39.     {  
  40.         System.out.println("Person類可以吃飯");  
  41.     }  
  42. }  
  43.   
  44. //定義一個Worker類直接實現walk接口,同時要實現兩個父接口中的抽象方法  
  45. class Worker implements Walk  
  46. {  
  47.     public void speak()  
  48.     {  
  49.         System.out.println("Worker類可以說話");  
  50.     }  
  51.     public void eat()  
  52.     {  
  53.         System.out.println("Worker類可以吃飯");  
  54.     }  
  55.     public void walk()  
  56.     {  
  57.         System.out.println("Worker類可以走路");  
  58.     }  
  59. }  
  60.   
  61.   
  62.   
  63.   
  64. public class InterfaceTest {  
  65.       
  66.     public static void main(String[] args) {  
  67.         //實例化兩個對象,輸出對應結果  
  68.         Person p = new Person();  
  69.         p.eat();  
  70.         p.speak();  
  71.           
  72.         Worker w = new Worker();  
  73.         w.eat();  
  74.         w.speak();  
  75.         w.walk();  
  76.     }  
  77. }  

代碼截圖:



代碼解析:

該代碼演示了接口的繼承,接口的實現

比較簡單,這裏就略過了



修飾符詳解

訪問控制修飾符

public:公有的,被public修飾的部分可以被任何程序訪問

protected:受保護的,被它修飾的成員只能由同包中的類或者其子類訪問

default(默認):不寫修飾符就是默認的,別寫上defalut啊!同包與同類可見

private:私有的,是Java實現封裝的關鍵,被修飾的成員變量與方法只能被類本身訪問,同包也不行哦!


注意事項:

不能夠使用protected和private修飾類;要麼用public修飾,要麼不加任何修飾符


其他修飾符:

static:靜態修飾符

①靜態變量:

用static修飾的變量,在所有對象中共享的數據,都指向內存中的同一地址

即,任何對象對改值的修改都會使存儲空間的值發生改變


代碼演示:

  1. package com.jay.example;  
  2.   
  3. class Test  
  4. {     
  5.     //定義初始的值爲3  
  6.     static int a = 3;  
  7. }  
  8.   
  9. public class StaticTest {  
  10.     public static void main(String[] args) {  
  11.         //靜態成員變量可以直接通過類名進行訪問  
  12.         System.out.println(Test.a);  
  13.         //實例化兩個對象,在t1中修改a的值,發現t2中的a的值也發生改變  
  14.         Test t1 = new Test();  
  15.         t1.a = 4;  
  16.         Test t2 = new Test();  
  17.         System.out.println(t2.a);  
  18.           
  19.           
  20.         //輸出結果是:  
  21.         //3  
  22.         //4  
  23.         //說明了靜態變量都是公用一塊內存區域的,任何一個對象  
  24.         //對值的修改,都會改變對應內存區域的值  
  25.     }  
  26. }  

②靜態方法:

用static修飾的方法,要注意:

靜態方法中,只能夠訪問靜態數據或者直接調用靜態方法

可以直接通過類名進行調用

代碼演示:

  1. package com.jay.example;  
  2.   
  3. /* 
  4.  *因爲我們的main方法就是靜態的方法 
  5.  *所以我們直接在main方法外定義參數和方法 
  6.  *驗證靜態方法只能訪問靜態成員 
  7.  * */  
  8.   
  9. public class StaticTest2 {  
  10.       
  11.     //定義非靜態的數據與方法  
  12.     int a = 3;  
  13.     void test(){System.out.println("非靜態方法可不能被main調用啊");}  
  14.       
  15.     //定義靜態的數據和方法  
  16.     static int b = 4;  
  17.     static void test2()  
  18.     {System.out.println("靜態方法被main調用了");}  
  19.       
  20.       
  21.     public static void main(String[] args) {  
  22.           
  23.         //下面兩個語句,如果調用了是會報錯的,不信可以試試  
  24.         //System.out.println(a);  
  25.         //test();  
  26.           
  27.         System.out.println(b);  
  28.         test2();  
  29.           
  30.     }  
  31. }  

③靜態代碼塊

放在類聲明的內部,成員方法與構造方法的外部,該代碼塊會在該類第一次使用時

執行一次,就不會再執行了,通常是在這裏寫一些初始化的代碼

代碼演示:

  1. package com.jay.example;  
  2.   
  3. public class static3 {  
  4.     static  
  5.     {  
  6.         System.out.println("靜態代碼塊,通常用於類的初始化");  
  7.     }  
  8. }  

④複雜的成員的初始化問題

當靜態數據,靜態代碼塊,對象成員,構造方法等同時存在時,那麼成員的初始化順序又是怎樣呢?

其實,初始化順序是:(靜態變量,靜態初始化塊) --->(變量,變量初始化塊)---->構造器

下面我們通過代碼來驗證這一規律:

  1. package com.jay.example;  
  2.   
  3.   
  4. public class static3 {  
  5.     public static String staticStr = "靜態成員初始化";  
  6.     public String str = "普通成員初始化";  
  7.       
  8.     //構造方法  
  9.     public static3() {  
  10.         System.out.println("構造方法初始化");  
  11.     }  
  12.       
  13.     //普通的初始化塊  
  14.     {  
  15.         System.out.println(str);  
  16.         System.out.println("普通的初始化塊");  
  17.     }  
  18.       
  19.     //靜態的初始化塊  
  20.     static   
  21.     {  
  22.         System.out.println(staticStr);  
  23.         System.out.println("靜態的初始化塊");  
  24.     }  
  25.       
  26.       
  27.     public static void main(String[] args) {  
  28.         static3 st = new static3();  
  29.     }  
  30. }  

運行截圖:




final:最終修飾符

使用方法


①使用final修飾屬性(變量),此時的屬性爲常量;Java中利用public static final int AGE = 10;對常量進行標識

②空白final變量(沒初始化的):空白的final數據成員必須在構造方法中進行初始化,否則會報錯

③final常量作爲方法的參數,只能夠對final進行簡單的引用,可不能改變常量的值哦!

④用final來修飾方法:那麼該方法爲一個不可覆蓋的方法,如果父類有final修飾的方法,那麼子類繼承同一個方法

⑤用final來修飾類:那麼該類不可以被繼承,final類沒有子類;同時該類中所有的方法都默認爲final

⑥final並不涉及繼承,繼承取決於類的修飾符是public還是其他,是否可以繼承取決於該類是否對其子類可見

    如果一個方法前有private或static的修飾符,那麼系統在前面自動地加上final修飾



abstract:抽象修飾符

被abstract修飾的類爲抽象類,修飾的方法爲抽象方法


transient:

用於修飾不想序列化,持久化的成員


volatile:

保證可見性和防止重排序,用的比較少,是併發操作那塊的



枚舉類型

枚舉解析:

①作爲jdk 1.5 後引入的枚舉,用來代替以前定義多個同類型常量的public final static 

②用enum表示,作用類似於class關鍵字;

③構造方法不要用public修飾

④變量和方法的定義需要在枚舉值的後面!!!



用法示例:

簡單的枚舉:

  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 本程序演示的是枚舉的最簡單用法 
  5.  * 定義枚舉Color有三個值,演示了switch和增強for循環遍歷枚舉 
  6.  * 中所有的原始的方法 
  7.  * */  
  8.   
  9. enum Color  
  10. {  
  11.     BLUE,RED,YELLOW;  
  12. }  
  13.   
  14. public class EnumTest {  
  15.     public void printColor(Color color)  
  16.     {  
  17.         switch(color)  
  18.         {  
  19.             case BLUE:  
  20.             System.out.println("輸出藍色!");  
  21.             break;  
  22.               
  23.             case RED:  
  24.             System.out.println("輸出紅色!");  
  25.             break;  
  26.               
  27.             case YELLOW:  
  28.             System.out.println("輸出黃色!");  
  29.             break;  
  30.         }             
  31.     }  
  32.     public static void main(String[] args) {  
  33.         EnumTest test = new EnumTest();  
  34.         test.printColor(Color.BLUE);  
  35.         test.printColor(Color.RED);  
  36.         test.printColor(Color.YELLOW);  
  37.           
  38.         //當然也可以直接用增強for循環來遍歷枚舉中所有的值:  
  39.         //可以通過values()方法獲得枚舉的數組  
  40.         for(Color c : Color.values())  
  41.         {  
  42.             System.out.println(c);  
  43.         }  
  44.     }  
  45. }  

運行截圖:




深一步的使用:

  1. package com.jay.example;  
  2.   
  3. /* 
  4.  * 本代碼演示的是枚舉類的進一步使用 
  5.  * 和類一樣,枚舉可以定義自己的屬性和方法,但是 
  6.  * 必須寫在枚舉列表的後面,不然會報編譯時錯誤 
  7.  * */  
  8.   
  9.   
  10.   
  11.   
  12. public class EnumTest2 {  
  13.       
  14.     public enum Color  
  15.     {  
  16.         //枚舉可以像一般的類一樣添加方法和屬性  
  17.         Red("紅色"),BLUE("藍色"),YELLOW("黃色");  
  18.           
  19.         //構造方法,不要寫public修飾!  
  20.         Color(String value)  
  21.         {  
  22.             this.value = value;  
  23.         }  
  24.           
  25.         //定義一個成員變量  
  26.         private final String value;  
  27.           
  28.         //定義一個獲取後面值得方法  
  29.         public String getValue()  
  30.         {  
  31.             return value;  
  32.         }  
  33.           
  34.           
  35.     }  
  36.       
  37.   
  38.       
  39.     public static void main(String[] args) {  
  40.         EnumTest2 test = new EnumTest2();  
  41.         //可以通過for循環調用獲得枚舉中所有的值  
  42.         for(Color color : Color.values())  
  43.         {  
  44.             System.out.println(color);  
  45.             System.out.println(color.getValue());  
  46.         }  
  47.           
  48.         //可以通過ordinal獲得枚舉值在枚舉中的索引位置,從0開始的  
  49.         System.out.println(Color.BLUE.ordinal());  
  50.           
  51.         //枚舉默認實現了java.lang.Comparable接口,可以直接調用compareTo對枚舉值進行比較  
  52.         //這裏Red在Blue前面,所以是-1  
  53.         System.out.println(Color.Red.compareTo(Color.BLUE));  
  54.           
  55.     }  
  56. }  

運行截圖:



小結:

在這裏,我們僅僅演示了enum枚舉類型的兩種基本用法,

如果有興趣深入研究枚舉的可以參考以下文檔:Java枚舉類型詳解

http://pan.baidu.com/s/1o6qHLUy



封裝:

將數據與數據操作綁定到一個類中,這樣的方法就保證了程序中的數據不會受到外部代碼的影響
在Java中通常是將屬性設置爲private,然後再類中設置getXxx()和putXxx()方法對數據進行操作
從而保證代碼的獨立性,而且能夠比較容易地對程序進行維護和修改




總結:

在面向對象的最後一節,在這一節中我們對抽象類,接口
各種修飾符,枚舉和封裝進行了深入的解析
Java面向對象知識點到此結束,我們學會的僅僅是基礎
需要在編程中進行鞏固,大家要做下相關的編程題目
做多了,知識點也就記得了!



如果文中有遺漏,錯誤,好的建議;
望讀者指出,萬分感激!!(*^__^*) 嘻嘻……


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