2013年2月15日 星期五

[Java]1-物件導向大補丸 Class 類別與巢狀類別(內部類別)


第一節-Class / 內部類別or「巢狀類別」(Nested class)

在類別中您還可以定義類別,稱之為內部類別(Inner class) 是可完整定義或是匿名(anonymous)的inner類別.主要應用在事件處理上.
內部類別可以分為四種:靜態內部類別(Static  inner class)、成員內部類別(Member inner class)區域(局部)內部類別(Local inner class)(包含方法內類【Method-local Inner Classes)匿名內部類別(Anonymous inner class)
◎方法內部類別只能存取方法內final的區域變數變數.可以用在內部類別修飾詞public, protected, private, final, strictfp, abstract, static(會變成static nested class
部類別要負責產生inner類別型別的物件.若是要產生其他的類別的inner物件,首先要產生該類別型別的物件ref.然後用以下的語法來產生它的inner類別物件:外部類別名稱.inner類別名稱 innerRef = ref.new inner類別名稱();
內部類別可繼承自一個class但可實做多個介面參考,匿名類別只能實做一個介面,this內部類別的參考,若欲取的外部類別的參考則需使用MyOuter.this。
一般內類&方法內類不可以是static的,即不可擁有static成員 → 一旦為static就是靜態內類.
一般內類它可以被當做外類的一個“實例變數”來看待。因此可使用publicprotecteddefaultprivate。只是注意:要在外類的non-static函數外産生該內類物件,必須以OuterClassName.InnerClassName的形式指定該內類物件的類型申明一般內類必須得關聯至其外類的某個物件
Inner Classes的instantiation方式,若是在Outer class的話,直接使用一般的方式就可以了。若是在Outer class以外的class要instantiate該inner class,則一定要透過outer class的reference才行。例:
MyOuter mo = new MyOuter();                               //creating outer class reference
MyOuter.MyInner mi = mo.new MyInner();           //creating inner class reference
要一行解決的話可以這樣寫:MyOuter.MyInner mi = new MyOuter().new MyInner();   //同樣是透過outer class reference



方法內類它屬於範圍型內類,也就是說你無法在方法外來調用內類,從這一點來講它可視爲方法的局部變數。但是,雖然有它的範疇性,畢竟內類還是類,它不會像局部變數那樣隨著方法的返回就消失了,它仍舊被java視爲類。
      A方法內類可以直接訪問外類的任何成員
      B方法內類只能訪問該方法中final型局部變數和final型的方法參數
      C.方法內類不可有任何接入控制符修飾(這一點與局部變數相同)
Method-local Inner Classes可以直接叫用outer class的所有variable還有enclosing method內標記為final的variable。(標記為final才看得到該變數)
MyOuter mo = new MyOuter();  //creating outer class reference
MyOuter.MyInner mi = mo.MyInner();  //creating inner class reference

-----------------------------------------------------------------------------------------------------
public class OuterClass{
        private double d1=1.0;
        public abstract class Inner1{ //內部類可以定義成abstract
          public abstract double methoda();
       }  //-------內部類還可以在內部被繼承-------
        class AnotherInner extends Inner1 {
                public double methoda(){return 1.0;}
        }  //-------------------------------------------------
       public static void main(String[] args){
        }  //------------內部類可以繼承外部類-------------
        public class Inner2 extends OuterClass{
        }      }
----------------------------------------------------------------------------------------------------------------

靜態內類
靜態內類會自動成為頂級(top-level)類即普通的類。可以置於介面中。它在産生其物件時不需要存在一個外類物件。它可被視爲static函數。
靜態內部類中的方法(無論是靜態的方法還是非靜態的方法)只能直接訪問外部類中的靜態成員,要訪問外部類中的非靜態成員,則必須創建外部類的物件。由於靜態內部類別會在載入時即配置記憶體空間,所以靜態內部類別無法直接存取外圍類別中的非static成員。如果需要存取外圍類別的非static成員,必需先將外圍類別實體化,再透過實體化後的物件來存取。
你無法在static inner class物件中存取enclosing class物件(指包住它的那個outer class)。
其類別內可擁有static data tmember或是static member function,更進一步的擁有static inner class。
local inner class:位於方法內的類別宣告,可以存取方法內的final local variable,有點像closure。
 Static nested classinstantiation方法(注意與一般inner class的不同):
MyOuter.Nested mn = new MyOuter.Nested(); //don’t need outer class reference


匿名類
它實際上是繼承new類的一個無名類。New傳回的reference會被自動向上轉型。匿名類不能擁有構造器,但是可以通過其基類默認或帶參數的構造器來申明。
匿名類添加任何修飾符(遵循超類的修飾符),也不可實現介面、抛出異常。
anonymous inner class:直接實體化之不具名類別,其必需繼承已存在base類別或實作已存在介面。
匿名內部類別不能擁有建構式,當其繼承的base class需要初使化時則將引數直接傳入,若是本身需要初始化則在定義處執行初始化動作或用instance initialization(實體初值設定式)。
所謂匿名類別(Anonymous inner class)就是沒有宣告名稱,直接以new 關鍵字來建立的類別實體所以根本不用宣告存取修飾子及implements inerface or extends other class
編譯含有inner類別的檔案後,會替每個inner類別產生獨立的.class檔案.它的檔名為"外部類別名稱$內部類別名稱.class".無名的inner類別檔案名字為"外部類別名稱$編號.class".其中的編號從1開始遞增
static inner class:這裡的靜態是指這個內部類別不需要一個外部類別的實體就可以直接實體化,使用時就像一般類別一樣,同樣也可用import直接引用(把外部類別當成是套件的一個階層),所以跟inner class其實是不太一樣的。

例:    
1
import OuterClass.InnerClass_2; //對nest interface也是如此
      Anonymouse inner class的寫法一定要會,參照下例。
1.方法一
public class X{                   
  public String showMe(){
    return "This is X";
  }    
class Y{
    X z = new X(){
      public String showMe(){
        return "This is Z";
    }              
    };          //注意分號別漏掉
}}
2.方法二
interface X{              
 public String showMe();
}        
class Y{
  X z = new X(){
    public String showMe(){
      return "this is z";
    }
  };      //只能實作一個(one and only one)interface
}
3.
方法三
class X{                    
  public void showMe(Y m){
    System.out.println("this is showMe method");
  };}        
interface Y{
  void showNothing();

public class Z{
  public static void main(String[] arg){
    X i = new X();

    i.showMe(new Y(){
        public void showNothing(){         
        }   }    ); }    }

1 則留言:

  1. greatest java inner class article ever I've read, thank you~

    回覆刪除