1. 程式人生 > >8--黑馬程式設計師---技術總結之抽象類、內部類

8--黑馬程式設計師---技術總結之抽象類、內部類

、期待與您交流! ----------------------

一.抽象類

      1.抽象類的概念
      在面向物件的概念中,所有的物件都是通過類來描繪的,但是反過來,並不是所有的類都是用來描繪物件的,如果一個類中沒有
包含足夠的資訊來描繪一個具體的物件,這樣的類就是抽象類。
      抽象類往往用來表徵對問題領域進行分析、設計中得出的抽象概念,是對一系列看上去不同,但是本質上相同的具體概念的抽象。
      比如,在一個圖形編輯軟體的分析設計過程中,就會發現問題領域存在著圓、三角形這樣一些具體概念,它們是不同的,但是它
們又都屬於形狀這樣一個概念,形狀這個概念在問題領域並不是直接存在的,它就是一個抽象概念。而正是因為抽象的概念在問題領
域沒有對應的具體概念,所以用以表徵抽象概念的抽象類是不能夠例項化的。通常在程式設計語句中用abstract修飾的類是抽象類。在
Java中,含有抽象方法的類稱為抽象類,不能用來生成物件。抽象類是不完整的,它只能用作基類。在面向物件方法中,抽象類主要
用來進行型別隱藏和充當全域性變數的角色。
      抽象類的宣告格式為
 abstract class A {
  ···
 }

        2.抽象類的特點
        1)abstract類中可以有abstract方法
與普通的類相比,abstract類可以有abstract方法。對於abstract方法,只允許宣告,不允許實現,而且不允許使用final修飾abstract方
法。下面的AbstractDemo1類中的min()方法是abstract方法。

  1. abstract class AbstractDemo1 {  
  2.     abstract int min(int x,int y);  //抽象方法不允許實現  
  3.     int max(int x,int y) {          //非抽象方法必須實現  
  4.         return x>y?x:y;  
  5.     }  
  6. }  
        當然,反之,有抽象方法的類一定是抽象類
        注意:abstract類也可以沒有abstract方法。

         2)abstract類不能用new運算子建立物件
        對於abstract類,不能使用new運算子建立該類的物件,需產生其子類,由子類建立物件,如果一個類是abstract類的子類,它必須具體實現父類的abstract方法,這就是為什麼不允許使用final修飾abstract方法的原因。在下面的程式碼示例,使用了abstract類。

  1. <
    spanstyle="font-size:12px;">public class AbstractDemo2 {  
  2.     /**使用抽象類,併為之建立物件,呼叫其抽象方法  
  3.      * @param args  
  4.      */  
  5.     public static void main(String[] args) {  
  6.         // TODO Auto-generated method stub  
  7.         A a;   //A a = new A();是非法的,因為abstract類不能用new運算子建立物件  
  8.         B b = new B();  
  9.         int max = b.max(12, 13);    //呼叫最大值方法算最大值  
  10.         int min = b.min(12, 13);    //呼叫最小值方法算最小值  
  11.         System.out.println("12和13的最大值是" + max);   //輸出結果是:12和13的最大值是13  
  12.         System.out.println("12和13的最小值是" + min);   //輸出結果是:12和13的最小值是12  
  13.     }  
  14. }  
  15. abstract class A {  
  16.     abstract int min(int x, int y);   //定義抽象方法算最小值  
  17.     int max(int x, int y) {           //定義抽象方法算最大值  
  18.         return x > y ? x : y;          //返回最大值  
  19.     }  
  20. }  
  21. class B extends A {  
  22.     int min(int x, int y) {           //abstract方法必須實現  
  23.         return x <y ? x : y;          //返回最小值  
  24.     }  
  25. }</span>
    一個abstract類只關心它的子類是否具有某種功能,並不關心功能的具體行為,功能的具體行為由子類負責實現,抽象類中的抽象方法可以強制子類必須給出這些方法的具體實現。
        在下面的程式碼示例中,有一個abstract的“圖形”類,圖形類要求其子類都必須有具有計算面積的功能。

  1. public class AbstractDemo3 {  
  2.     /**建立一個abstract的圖形類,要求子類必須具有計算面積的功能  
  3.      * @黑馬ZWF  
  4.      */  
  5.     public static void main(String[] args) {  
  6.         // TODO Auto-generated method stub  
  7.         梯形  t = new 梯形(2.0, 5.2, 12.3);  
  8.         圓 y = new 圓(5.6);  
  9.         System.out.println("該梯形的面積是:" + t.求面積());   //輸出結果是:該梯形的面積是:44.28  
  10.         System.out.println("該圓的面積是:" + y.求面積());     //輸出結果是:該圓的面積是:98.52034561375999  
  11.     }  
  12. }  
  13. abstract class 圖形 {     //定義抽象類  
  14.     public abstract double 求面積();       //定義抽象方法求面積();這樣可以要求子類必須實現  
  15. }  
  16. class 梯形  extends 圖形 {  //定義梯形類繼承圖形類  
  17.     double a, b, h;  
  18.     梯形(double a, double b, double h){  
  19.         this.a = a;  
  20.         this.b = b;  
  21.         this.h = h;  
  22.     }  
  23.     public double 求面積() {           //實現圖形的抽象方法  
  24.         return ((1/2.0) * (a + b) * h);  
  25.     }  
  26. }  
  27. class 圓 extends 圖形 {        //定義圓類繼承圖形類  
  28.     double r;  
  29.     final double PI = 3.1415926535;  
  30.     圓(double r) {  
  31.         this.r = r;  
  32.     }  
  33.     public double 求面積() {           //實現圖形的抽象方法  
  34.         return PI * r * r;  
  35.     }  
  36. }  

        3.比較區別
        與具體類比較
        1)抽象類不能直接例項化,並且對抽象類使用new運算子會導致編譯時錯誤。雖然一些變數和值在編譯時的型別可以是抽象的,但是這樣的變數和值必須或者為 null,或者含有對非抽象類的例項的引用(此非抽象類是從抽象類派生的)。
        2)允許(但不要求)抽象類包含抽象成員。
        3)抽象類不能被密封。

        與介面比較
         抽象類表示該類中可能已經有一些方法的具體定義,但是介面就僅僅只能定義各個方法的介面(方法名,引數列表,返回型別),並不關心具體細節。
        介面是引用型別的,和抽象類的相似之處有三點:
        1)不能例項化;
        2)包含未實現的方法宣告;
        3)派生類必須實現未實現的方法,抽象類是抽象方法,介面則是所有成員(不僅是方法包括其他成員)。
        抽象類與介面緊密相關。然而介面又比抽象類更抽象,這主要體現在它們的差別上:
        1)類可以實現無限個介面,但僅能從一個抽象(或任何其他型別)類繼承,從抽象類派生的類仍可實現介面,從而得出介面是用來解決多重繼承問題的。
        2)抽象類當中可以存在非抽象的方法,可介面不能,且它裡面的方法只是一個宣告必須用public來修飾沒有具體實現的方法。
        3)抽象類中的成員變數可以被不同的修飾符來修飾,可介面中的成員變數預設的都是靜態常量(static final)。
        4)抽象類是物件的抽象,然而介面是一種行為規範。
        抽象類裡面可以有非抽象方法但接口裡只能有抽象方法 宣告方法的存在而不去實現它的類被叫做抽像類(abstract class),它用於要建立一個體現某些基本行為的類,併為該類宣告方法,但不能在該類中實現該類的情況。不能建立abstract 類的例項。然而可以建立一個變數,其型別是一個抽像類,並讓它指向具體子類的一個例項。不能有抽像建構函式或抽像靜態方法。Abstract 類的子類為它們父類中的所有抽像方法提供實現,否則它們也是抽像類為。取而代之,在子類中實現該方法。知道其行為的其它類可以在類中實現這些方法。介面(interface)是抽像類的變體。在介面中,所有方法都是抽像的。多繼承性可通過實現這樣的介面而獲得。介面中的所有方法都是抽像的,沒有一個有程式體。介面只可以定義static final成員變數。介面的實現與子類相似,除了該實現類不能從介面定義中繼承行為。當類實現特殊介面時,它定義(即將程式體給予)所有這種介面的方法。然後,它可以在實現了該介面的類的任何對像上呼叫介面的方法。由於有抽像類,它允許使用介面名作為引用變數的型別。通常的動態聯編將生效。引用可以轉換到介面型別或從介面型別轉換,instanceof 運算子可以用來決定某物件的類是否實現了介面。
        4.抽象類的用法要求總結
        1)abstract class 在 Java 語言中表示的是一種繼承關係,一個類只能使用一次繼承關係。但是,一個類卻可以實現多個interface。
        2)在abstract class 中可以有自己的資料成員,也可以有非abstarct的成員方法,而在interface中,只能夠有靜態的不能被修改的資料成員(也就是必須是static final的,不過在 interface中一般不定義資料成員),所有的成員方法都是abstract的。
        3)abstract class和interface所反映出的設計理念不同。其實abstract class表示的是"is-a"關係,interface表示的是"like-a"關係。
        4)實現抽象類和介面的類必須實現其中的所有方法。抽象類中可以有非抽象方法。介面中則不能有實現方法。
        5)介面中定義的變數預設是public static final 型,且必須給其初值,所以實現類中不能重新定義,也不能改變其值。
        6)抽象類中的變數預設是 friendly 型,其值可以在子類中重新定義,也可以重新賦值。
        7)介面中的方法預設都是 public,abstract 型別的。

         二.內部類

         1)非靜態成員內部類
          A:定義,:在一個外部類中有成員變數和成員方法,那麼成員內部類就是把整個一個類當成了外部類的成員對待了
          B: 訪問方式:內部類訪問外部類,內部類可以直接訪問外部類,包括私有成員,因為內部類擁有外部類的引用是類名.this。外部類訪問內部類,外部類訪問外部類的成員,必須要建立內部類的物件
          格式:外部類名.內部類名 = 外部類物件.內部類物件;
          Outer.Inner oi = new Outer().new Inner();//outer代表外部類,Inner代表內部類
          C:存放位置:在外部類裡,在外部類的成員方法外.
          D:修飾符:final、abstract、public、private、protected和static等,那麼被static修飾的就是下面所說的靜態內部類.

  1. <spanstyle="font-size:12px;">public class InnerDemo1 {  
  2.     /**展示非靜態成員內部類的建立方式  
  3.      * @黑馬ZWF  
  4.      */  
  5.     public static void main(String[] args) {  
  6.         // TODO Auto-generated method stub  
  7.         Outer.Inner oi = new Outer().new Inner();  //非靜態成員內部類的建立方式  
  8.         oi.show();          //呼叫內部類的show()方法  
  9.     }  
  10. }  
  11. class Outer {  
  12.     private String name = "張三"; //設定私有變數  
  13.     class Inner {  
  14.         public void show() {  
  15.             System.out.println(Outer.this.name);    //讀取name變數並列印  
  16.         }  
  17.     }  
  18. }</span>
    2)靜態內部類
       A:定義,就是在成員內部類的基礎上加上static
       B:格式:外部類名.內部類名 = 外部類名.內部類物件;
       Outer.Inner oi = new Outer.Inner();
       C:存放位置:和成員內部類一樣,就是多了個static

  1. public class InnerDemo2 {  
  2.     /**展示靜態內部類的建立方式  
  3.      * @黑馬ZWF  
  4.      */  
  5.     public static void main(String[] args) {  
  6.         // TODO Auto-generated method stub  
  7.         Outer.Inner oi1 = new Outer.Inner();    //靜態內部類的建立方式  
  8.         oi1.show();                 //輸出結果是:Hello World!  
  9.         Outer.Inner2 oi2 = new Outer.Inner2();  
  10.         oi2.show2();                //輸出結果是:Hello World!2  
  11.     }  
  12. }  
  13. class Outer {  
  14.     static class Inner {  
  15.         public void show() {  
  16.             System.out.println("Hello World!");  
  17.         }  
  18.     }  
  19.     static class Inner2 {  
  20.         public static void show2() {  
  21.             System.out.println("Hello World!2");    //注意不要在非靜態的內部類中定義靜態的方法  
  22.         }  
  23.     }  
  24. }  
         3)區域性內部類
         A:定義,在外部類成員方法中定義的內部類,他更像區域性變數
         B: 注意:
        第一:方法內部類只能在定義該內部類的方法內例項化,不可以在此方法外對其例項化。
        第二:方法內部類物件不能使用該內部類所在方法的非final區域性變數。因為方法的區域性變數位於棧上,只存在於該方法的生命期內。當一個方法結束,其棧結構被刪除,區域性變數成為歷史。但是該方法結束之後,在方法內建立的內部類物件可能仍然存在於堆中!例如,如果對它的引用被傳遞到其他某些程式碼,並存儲在一個成員變數內。 正因為不能保證區域性變數的存活期和方法內部類物件的一樣長,所以內部類物件不能使用它們。
        第三:方法內部類的修飾符。與成員內部類不同,方法內部類更像一個區域性變數 。可以用於修飾方法內部類的只有final和abstract。
        第四:靜態方法內的方法內部類。靜態方法是沒有this引用的,因此在靜態方法內的內部類遭受同樣的待遇,即:只能訪問外部類的靜態成員。

        (4)匿名類:匿名類是不能有名稱的類,所以沒辦法引用它們。必須在建立時,作為new語句的一部分來宣告它們。這就要採用另一種形式的new語句,也就是匿名類。這種形式的new語句宣告一個新的匿名類,它對一個給定的類進行擴充套件,或者實現一個給定的介面。它還建立那個類的一個新例項,並把它作為語句的結果而返回。要擴充套件的類和要實現的介面是new語句的運算元,後跟匿名類的主體。如果匿名類對另一個類進行擴充套件,它的主體可以訪問類的成員、覆蓋它的方法等等,這和其他任何標準的類都是一樣的。如果匿名類實現了一個介面,它的主體必須實現介面的方法。
        A:前提:內部類可以繼承或實現一個外部類或者介面。
        B:格式為:new 外部類名或者介面名(){覆蓋類或者介面中的程式碼,(也可以自定義內容。)}
        C:簡單理解:就是建立一個帶內容的外部類或者介面的子類的匿名物件。
        D: a,繼承式的匿名類
                b,介面式(也可以叫實現式的,名字無所謂)的匿名類
                 c,引數式的匿名類

程式碼示例:

  1. public class InnerDemo3 {  
  2.     /**匿名內部類的使用  
  3.      * @黑馬ZWF  
  4.      */  
  5.     public static void main(String[] args) {  
  6.         // TODO Auto-generated method stub  
  7.         Outer o = new Outer();  
  8.         o.print();  
  9.     }  
  10. }  
  11. class Demo {  
  12.     public void show() {  
  13.         System.out.println("Hello World!");  
  14.     }  
  15. }  
  16. class Outer {  
  17.     public void print() {   //匿名內部類  
  18.         new Demo() {  
  19.         }.show();  
  20.     }  
  21. }  


            匿名內部類的注意事項
         注意匿名類的宣告是在編譯時進行的,例項化在執行時進行。這意味著for迴圈中的一個new語句會建立相同匿名類的幾個例項,而不是建立幾個不同匿名類的一個例項。
在使用匿名內部類時,要記住以下幾個原則:
     1)匿名內部類不能有構造方法。  
     2)匿名內部類不能定義任何靜態成員、方法和類。  
     3)匿名內部類不能是public,protected,private,static。  
     4)只能建立匿名內部類的一個例項。
        5)一個匿名內部類一定是在new的後面,用其隱含實現一個介面或實現一個類。  
     6)因匿名內部類為區域性內部類,所以區域性內部類的所有限制都對其生效。
        7)內部類只能訪問外部類的靜態變數或靜態方法。
        8)匿名類和內部類中的中的this :有時候,我們會用到一些內部類和匿名類。當在匿名類中用this時,這個this則指的是匿名類或內部類本身。這時如果我們要使用外部類的方法和變數的話,則應該加上外部類的類名
          匿名內部類的作用
        Java的內部類和C++中的巢狀類有本質的不同:C++的巢狀類沒有指向包裝類的控制代碼。僅僅表達一個封裝的概念;但是Java的內部類不同,它可以訪問包裝類的成員(這表示它擁有指向包裝類的控制代碼)。
        匿名內部類是內部類的一種簡化寫法:return new Wrapper {
                                        ...
                                     };
      等價於:Wrapped extends Wrapper {
          ...
          }
          return new Wrapped();
      難道匿名內部類就只這一點作用嗎?考慮一下下面的例子

  1. interface ICount {  
  2.     int count();  
  3. }  
  4. class Parent {  
  5.     int i = 0;  
  6.     int count() {  
  7. 相關推薦

    8--黑馬程式設計師---技術總結抽象部類

    、期待與您交流! ---------------------- 一.抽象類       1.抽象類的概念       在面向物件的概念中,所有的物件都是通過類來描繪的,但是反過來,並不是所有的類都是用來描繪物件的,如果一個類中沒有 包含足夠的資訊來描繪一個具體的物

    7--黑馬程式設計師--技術總結幾個重要的關鍵字

    、期待與您交流! ---------------------- 一.static關鍵字           static表示“全域性”或者“靜態”的意思,用來修飾成員變數和成員方法,也可以形成靜態static程式碼塊,但是Java語言中沒有全域性變數的概念。   

    5--黑馬程式設計師--技術總結面向物件

    、期待與您交流! ---------------------- 一.什麼是面向物件? 1.面向物件的定義         面向物件是一種對現實世界理解和抽象的方法,是計算機程式設計技術發展到一定階段後的產物。早期的計算機程式設計是基於面向過程

    9--黑馬程式設計師--技術總結多執行緒

    、期待與您交流! ---------------------- 一.多執行緒的概念 以往開發的程式大多是單執行緒的,即一個程式只有一條從頭至尾的執行線索。然而現實世界中的很多過程都具有多條線索同時動作的特性:例如,我們可以一邊看電視,一邊活動胳膊,如果

    4--黑馬程式設計師--技術總結陣列

    <span style="white-space: pre; color: rgb(68, 68, 68); font-family: 'Microsoft Yahei', 微軟雅黑, Tahoma, Arial, Helvetica, STHeiti; font-

    黑馬程式設計師——方法總結網編

    ------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! ------- /* 1.IP地址類 InetAddress 所在包:java.net.InetAddress

    黑馬程式設計師----Java基礎集合(一)

    ------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

    黑馬程式設計師----Java基礎String

    ------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

    黑馬程式設計師——java拾遺代理及AOP

    動態代理其實就是java.lang.reflect.Proxy類動態的根據您指定的所有介面生成一個class 位元組碼,該class會繼承Proxy類,並實現所有你指定的介面(您在引數中傳入的介面陣列);然後再利用您指定的classloader將 class 位元組碼載

    JavaSE--抽象部類接口

    -- ann 固定 com init 外部 普通 new t eve 一、抽象類   當事物不能具體描述時可將事物抽象化,只對其應有的行為進行簡單的描述而不進行深度具體的描述,這樣就產生了抽象類,使用abstract關鍵字對類進行修飾內部方法也是用abstract進行描述。

    黑馬程式設計師技術部落格哲學家吃飯問題

    ----------- android培訓、java培訓、java學習型技術部落格、期待與您交流! ------------ 哲學家就餐:有五個哲學家繞著圓桌坐,每個哲學家面前有一碗麵,兩人之間有一支筷子,這樣每個哲學家左右各有一支筷子。哲學家有2個狀態,思考或者拿起筷子吃

    黑馬程式設計師——Java高新技術反射學習總結

                                                                                        反射學習總結 基礎補充: Java程式中的各個Java類屬於同一類事務,描述這類事務的Java類名就是C

    黑馬程式設計師 java程式設計面向物件學習筆記總結

    ---------------------- ASP.Net+Unity開發、.Net培訓、期待與您交流! ---------------------- 繼承: 在java中,在我們要對一個事物進行封裝時,發現有某一個類的特性和要封裝的這個 類的特性相同,而我們可以在這個

    黑馬程式設計師----Java基礎反射

    ------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

    黑馬程式設計師----Java基礎GUI

    ------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

    黑馬程式設計師----Java基礎IO包中其它

    ------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

    黑馬程式設計師----Java基礎多執行緒

    ------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

    黑馬程式設計師----Java基礎面向物件(最終篇)

    ------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

    黑馬程式設計師----Java基礎面向物件(封裝 繼承 多型)(二)

    ------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

    黑馬程式設計師----Java基礎面向物件(封裝 繼承 多型)

    ------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g