1. 程式人生 > >技術篇7.0類的高級特性

技術篇7.0類的高級特性

它的 clas sel abstract tde 反射機制 查看 不一定 靜態內部類

  類除了具有普通的特性之外,還具有一些高級特性,如包、內部類等。包在整個管理中起到了非常重要的作用,使用包可以有效地管理繁雜的類文件,解決類重名問題,當在類中配合與權限修飾符使用時,可以控制其他人對類成員的訪問。同時在Java語言中一個更為有效的隱藏實現細節的技巧是使用內部類,通過使用內部類機制可以向上轉型為被內部類實現的公共接口。由於在類中可以定義多個內部類,所以實現接口的方式也不止一個,只要將內部類中的方法設置為類最小範圍的修飾權限即可將內部類的實現細節有效地隱藏。

  抽象類

  (概念)所謂抽象類就是只聲明方法的存在而不去具體實現它的類。抽象類不能被實例化,也就是不能創建其對象。在定義抽象類時,要在class關鍵字前面加上abstract關鍵字。定義抽象類,語法格式:

  abstract class 類名{

    類體

  }

  在抽象類中創建的,沒有實際意義的,必須要子類重寫的方法稱為抽象方法。抽象方法只有方法的聲明,而沒有方法的實現,用abstract關鍵字進行修飾。聲明一個抽象方法的基本格式:

  abstract<方法返回值類型>方法名(參數列表);

  方法返回值類型:必選參數,用於指定方法的返回值類型,如果該方法沒有返回值,可以使用關鍵字void進行標識。方法返回值的類型可以是任何Java數據類型。

  方法名:必選參數,用於指定抽象方法中所需的參數。當存在多個參數時,各參數之間使用逗號分隔。方法的參數可以使任何Java數據類型。

  public abstract void harverst(); 在抽象類中添加一個抽象方法。

  註意:抽象方法不能使用private或static關鍵字盡心修飾。

  包含一個或多個抽象方法的類必須被聲明為抽象類。因為抽象方法沒有定義方法的實現部分,如果不聲明為抽象類,這個類將可以生成對象,這時當用戶調用抽象方法時,程序就不知道如何處理了。

  定義一個水果類fruit,該類為抽象類,並在該類中定義一個抽象方法,同時在其子類中銅鼓哦重寫的方法(@override)實現該抽象方法。

  內部類

  (概念)如果在一個類中再定義一個類,就將在類中再定義的那個類成為內部類。內部類可分為成員內部類和局部內部類以及匿名內部類。

    成員內部類

  (用法)在一個類中使用內部類可以在內部類中直接存取其所在類的私有成員變量。語法格式為:

  public class outerclass{

    private class innerclass{

      //...

    }

  }

  在內部類中可以隨意使用外部類的成員方法和成員變量,盡管這些類成員被修飾為private。盡管成員變量i以及成員方法g()都在外部類中被修飾為private,但在內部類中可以直接使用外部類中的類成員。

  技術分享

  內部類的實例一定要綁定在外部類的實例上,如果在外部類中初始化一個內部類對象,那麽內部類對象就會綁定在外部類對象上。內部類初始化方式與其他類初始化方式相同,都是使用new關鍵字。  

  外部類創建內部類實例時與其他類創建對象引用時相同。內部類可以訪問它的外部類的成員,但內部類的成員只有在內部類的範圍之內是可知的,不能被外部類使用。例如,如果將內部類的成員變量y再次賦值時,將會出錯,但是如果使用內部類對象引用調用成員變量y即可。圖中反映了內部類innerclass對象與外部類outerclass對象的關系。

  技術分享

  註意:如果在外部類和非靜態方法之外實例化內部類對象,需要使用“外部類.內部類”的形式指定該對象的類型。

  在主方法中,如果不適用doit()方法返回內部類對象引用,可以直接使用內部類實例化內部類對象,但由於是在主方法中實例化內部類對象,必須在new操作符之前提供一個外部類的引用。

  註意:在實例化內部類對象時,不能在new操作符之前使用外部類名稱那種形式來實例化內部類對象,而應該使用外部類的對象來創建其內部類對象。內部類對象會依賴於外部類對象,除非已經存在一個外部類對象,否則類中不會出現內部類對象。

    使用this關鍵字獲取內部類與外部類的引用

  如果外部類中定義的成員變量與內部類的成員變量名稱相同,可以使用this關鍵字。  

  在類中如果內部類與外部類遇到成員變量重名的情況可以使用this關鍵字進行處理,例如在內部類中使用this.x語句可以調用內部類的成員變量x,而使用thesamename.this.x語句可以調用外部類的成員變量x,即使用外部類名稱後跟一個點操作符和this關鍵字便可獲取外部類的一個引用。

  在內存中所有對象被放置在堆中,將方法以及方法中的形參或局部變量放置在棧中。在棧中的doit()方法執行內部類的對象,而內部類的對象與外部類的對象是相互依賴的,outer.this對象指向外部類對象。

  技術分享

    局部內部類

  (概念)局部內部類是指在類的方法中定義的內部類,它的作用範圍也是在這個方法體內。

  將內部類定義在sell()方法內部,但是有一點值得註意,內部類apple是sell()方法的一部分,並非selloutclass方法的一部分,所以在sell()方法的外部不能訪問該內部類,但是該內部類可以訪問當前代碼塊的常量以及此外部類的所有成員。

    匿名內部類

  (概念)在編寫程序代碼時,不一定要給內部類取一個名字,可以直接以對象名來代替。匿名內部類的所有實現代碼都需要在大括號之間進行編寫。

  說明:在圖形化編程的事件監控器代碼中,會大量使用匿名內部類,這樣可以大大簡化代碼,並增強代碼的可讀性。匿名內部類的語法格式如下:return new A(){……//內部類體};

  其中,A表示對象名。由於匿名內部類沒有名稱,所以匿名內部類使用默認構造方法來生成匿名內部類的對象。在匿名內部類定義結束後,需要加分號標識,這個分號並不代表定義內部類結束的標識,而代表創建匿名內部類的引用表達式的標識。

  註意:匿名內部類編譯以後,會產生以“外部類名$序號”為名稱的.class文件,序號以1~n排列,分別代表1~n個匿名內部類。

    靜態內部類

  (概念)在內部類前添加修飾符static,這個內部類就變為靜態內部類。一個靜態內部類中可以聲明static成員,但是在非靜態內部類中不可以聲明靜態成員。靜態內部類有一個最大的特點,就是不可以使用外部類的非靜態成員,所以靜態內部類在程序開發中比較少見。

  普通的內部類對象隱式地在外部保存了一個引用,指向創建它的外部類對象,但如果內部類被定義static時,它應該具有更多的限制。靜態內部類具有以下兩個特點:

  創建靜態內部類對象,不需要其外部類的對象。不能從靜態內部類的對象中訪問非靜態外部類的對象。

  註意:在內部類doitInner()方法中調用成員變量x,由於Inner被修飾為static形式,而成員變量x卻是非static類型的,所以在doitInner()方法中不能調用x變量。進行程序測試時,如果在每一個Java文件中都設置一個主方法,將出現很多額外的代碼,而程序本身並不需要這些主方法,為了解決這個問題,可以將主方法寫入靜態內部類中。如果編譯上述類,將生成一個名為staticInnerClass$Inner的獨立類和一個staticInnerClass類,只要使用staticInnerClass$Inner就可以運行主方法中的內容,這樣當測試完成需要將所有.class文件打包時,只要刪除staticInnerClass$Inner獨立類即可。

    內部類的繼承

  (概念)內部類也和其他普通類一樣可以被繼承,但是繼承內部類比繼承普通類要復雜一些,需要設置專門的語法來完成。

  在某個類繼承內部類時,必須硬性給予這個類一個帶參數的構造方法,並且該構造方法的參數為需要繼承內部類的外部類的引用,同時在構造方法體重使用a.super語句,這樣才為繼承提供了必要的對象引用。

  class類與Java反射

  通過Java反射機制,可以在程序中訪問已經裝載到jvm中的Java對象的描述,實現訪問、檢測和修改描述Java對象本身信息的功能。Java反射機制的功能十分強大,在Java.lang.reflect包中提供了對該功能的支持。

  眾所周知,所有Java類均繼承了object類,在object類中定義了一個getclass()方法,該方法返回一個類型為class的對象。代碼如下:Class textFieldC = textField.getClass();//textField為JTextField類的對象

  利用class類的對象textFieldC,可以訪問用來返回該對象的textFiled對象的描述信息。(理解為引用?)

  主要的描述信息如表:

  技術分享

  註意:在通過getFields()和getMethods()方法依次獲得權限為public的成員變量和方法時,還包含從超類中繼承到的成員變量和方法;而通過getDeclaredFields()和getDeclaredMethods()方法只是獲得在本類中定義的所有成員變量和方法。

    訪問構造方法

  在通過下列一組方法訪問構造方法時,將返回constructor類型的對象或數組。每個constructor對象代表一個構造方法,利用constructor對象可以操縱相應的構造方法。

  技術分享

  如果是訪問指定的構造方法,需要根據該構造方法的入口參數的類型來訪問。例如訪問一個入口參數類型依次為string和int型的構造方法,可以通過下面兩種方式實現。

  objectClass.getDeclaredConstructor(string.class,int.class);

  objectClass.getDeclaredConstructor(new Class[]{string.class,int.class});

  constructor類中提供的常用方法:

  技術分享

  通過java.lang.reflect.modifier類可以解析出getModifiers()方法的返回值所表示的修飾符信息,在該類中提供了一些列用來解析的靜態方法,既可以查看是否被指定的修飾符修飾,還可以以字符串的形式獲得所有修飾符。該類常用的靜態方法如表所示:

  技術分享

  (舉例)判斷constructor對象所代表的構造方法是否被private修飾,以及字符串形式獲得該構造方法的所有修飾符,代碼:

  int modifiers = constructor.getModifiers();

  boolean isEmbellishByPrivate=Modifier.isPrivate(modifiers);

  string embelishment = Modifier.toString(modifiers);

  反射訪問 ?

    訪問成員變量

  (應用)在通過下列一組方法訪問成員變量時,將返回Field類型的對象或數組。每個Field對象代表一個成員變量,利用Field對象可以操縱相應的成員變量。

  getFields()  getField(String name)  getDeclaredFields()  getDeclaredField(String name)

  如果是訪問指定的成員變量,可以通過該成員變量的名稱來訪問。(舉例)訪問一個名稱為birthday的成員變量,代碼如下:

  object.getDeclaredField("birthday");

  技術分享

  註意:1)在項目中創建一個MoreFields類,在該類中依次聲明一個int、float、boolean和string型的成員變量,並將它們設置為不同的訪問權限。2)通過反射訪問MoreFields類中的所有成員變量,將成員變量的名稱和類型信息輸出到控制臺,並分別將各個成員變量在修改前後的值輸出到控制臺。要訪問權限為private的成員變量s,需要執行setAccessible()方法,並將入口參數設為true,否則不允許訪問。

    訪問方法

  在通過下列一組方法訪問方法時,將返回method類型的對象或數組。每個method對象代表一個方法,利用method對象可以操縱相應的方法。

  getMethods()  getMethod(String name,Class<?>……parameterTypes)  getDeclaredMethods()  getDeclaredMethod(String name,Class<?>……parameterTypes)

  如果是訪問指定的方法,需要根據該方法的名稱和入口參數的類型來訪問。(舉例)訪問一個名稱為print、入口參數類型為string和int型的方法,可以通過下面兩種方式實現。

  objectClass.getDeclaredMethod("print".String.class,int.class);

  objectClass.getDeclaredMethod("print",new class[]{string.class,int.class});

  Method類中提供的常用方法:

  技術分享

  1)在項目中創建一個MoreMethod類,並編寫4個典型的方法。2)通過反射訪問MoreMethod類中的所有方法,將各個方法的名稱、入口參數類型、返回值類型等信息輸出到控制臺,並執行部分方法。在反射中執行具有可變數量的參數的構造方法時,需要將入口參數定義為二維數組。

  註意:在Java中,調用類的方法有兩種方式:對於靜態方法可以直接使用類名調用,對於非靜態方法必須使用類的對象調用。反射機制提供了比較另類的調用方式,可以根據需要指定要調用的方法,而不必在編程時確定。調用的方法不僅只限於public的,還可以是private的。本範例將使用反射機制調用math類的靜態方法sin()和string類的非靜態方法equals().

  小結:首先講解了抽象類,之後分別講解了內部類中的成員內部類、局部內部類、匿名內部類和靜態內部類,最後講解了反射。通過學習本章,讀者可以對內部類有一個更深層次的了解,並且能夠在別寫程序時熟練使用內部類。

  小結:首先講解了抽象類,之後分別講解了內部類中的成員內部類、局部內部類、匿名內部類和靜態內部類,最後講解了反射。通過學習,應對內部類有一個更深層次的了解,並且能夠在編寫程序時熟練應用內部類。

技術篇7.0類的高級特性