1. 程式人生 > >《Java程式設計思想》之為什麼需要內部類?

《Java程式設計思想》之為什麼需要內部類?

13、為什麼需要內部類?

1).內部類最吸引人注意的原因是:每個內部類都能獨立的繼承自一個(介面的)實現,所以無論外圍類是否已經繼承了某個就(介面的)實現,對於內部類都沒有影響。

2).一個類中以某種方式實現兩個介面。由於介面的靈活性,你有兩種選擇:使用單一類,或者使用內部類。從實現觀點看,以下倆種方式沒什麼區別。

interface A{}
interface B{}
 
class X implements A, B{}
 
class Y implements A{
   B makeB(){
      return new B(){
        
      };
   }
}
 
public class MultiInterfaces{
   static void takesA(A a){}
   static void takesB(B b){}
   public static void main(String[] args){
      X x = new X();
      Y y = new Y();
      takesA(x);
      takesA(y);
      takesB(x);
      takesB(y.makeB());
   }
}

3).如果擁有的是抽象類或具體的類,而不是介面,那就只能使用內部類才能實現多重繼承。

4).內部類還可以獲得其他一些特性(不是很理解!!):

·內部類可以有多個例項,每個例項都有自己的狀態資訊,並且與外圍類物件的資訊相互獨立。

·在單個的外圍類中,可以讓多個內部類以不用的方式實現同一介面,或繼承同一個類。

·建立內部類物件的時刻並不依賴外圍類物件的建立。

·內部類並沒有令人迷惑的“is-a”關係;它就是一個獨立的實體。

請看下面例子:

interface Selector{
   boolean end();
   Object current();
   void next();
}
public class Sequence{
   private Object[] objects;
   private int next = 0;
   public Sequence(int size){
      objects = new Object[size];
   }
   public void add(Object x){
      if(next < objects.length)
        objects[next++] = x;
   }
   private class SSelector implements Selector{
      private int  i = 0;
      public boolean end(){
        return i == objects.length;
      }
      public Object current(){
        return objects[i];
      }
      public void next(){
        if(i < objects.length)
           i++;
      }
   }
   public Selector getSelector(){
      return new SSelector();
   }
   public static void main(String[] args){
      Sequence sequence = new Sequence(10);
      for(int i = 0; i < 10; i++)
        sequence.add(Integer.toString(i));
      Selector selector = sequence.getSelector();
      while(!selector.end()){
        System.out.println(selector.current());
        selector.next();
      }
   }
}

如果Sequence不適用內部類,就必須宣告“Sequence是一個Selector”,對於某個特定的Sequence只能又一個Selector。同時,使用內部類很容易就能擁有另一個方法getRSelector(),用它來生成一個反方向遍歷的Selector。只有內部類才有這種靈活性

14、閉包是一個可呼叫的物件,它記錄了一些資訊,這些資訊來自於建立它的作用域。內部類是面向物件的閉包。因為它不僅包含外圍類物件(“建立內部類的作用域”)的資訊,還自動擁有一個指向此外圍物件的引用,在此作用域內,內部類操作所有成員,包括“private”成員。

15、Java最具有爭議的問題之一就是,人們認為Java應該包含某種類似指標的機制,以允許回撥。通過回撥

,物件能夠攜帶一些資訊,這些資訊允許它在稍後的某個時刻呼叫初始的物件。

通過內部類提供閉包的功能是完美的解決方案,它比指標更靈活、更安全。見下例:

interface Incrementable{
   void increment();
}
//外部類實現介面
class Callee1 implements Incrementable{
   private int  i = 0;
   public void increment(){
      i++;
      System.out.println(i);
   }
}
class MyIncrement{
   void increment(){
      System.out.println("MyIncrement.increment()");
   }
   static void func(MyIncrement myIncrement){
      myIncrement.increment();
   }
  
}
 
class Callee2 extends MyIncrement{
   private int i = 0;
   private void incr(){
      i++;
      System.out.println(i);
   }
   //內部類實現介面
   public class Closureimplements Incrementable{
      public void increment(){
        incr();
      }
   }
   Incrementable getCallBackReference(){
      return new Closure();//向上轉型
   }
}
class Caller{
   private Incrementable callBackReference;
   Caller(Incrementable callBackReference){
      this.callBackReference = callBackReference;
   }
   void go(){
      callBackReference.increment();
   }
}
public class Callbacks{
   public static void main(String[] args){
      Callee1 c1 = new Callee1();
      Callee2 c2 = new Callee2();
      MyIncrement.func(c2);
      Caller caller1 = new Caller(c1);
      Caller caller2 = new Caller(c2.getCallBackReference());
      caller1.go();
      caller1.go();
      caller2.go();
      caller2.go();
     
   }
}

   Callee2繼承自MyIncrement,有一個與Incrementable介面相同名字的increment()方法,但是兩者的Increment()方法行為不同。所以如果Callee2繼承了MyIncrement,就不能為了Incrementable的用途而覆蓋increment()方法,於是只能使用內部類獨立的實現Incrementable。還要注意,當建立了一個內部類時,並沒有在外圍類的介面中新增東西,也沒有修改外圍類的介面。

Callee2中內部類Closure 裡的getCallBackReference()方法,返回一個Incrementable的引用,無論誰獲得此引用,都只能呼叫increment(),除此之外沒有其他功能(不像指標那樣,允許你做很多事情)。

回撥的價值在於它的靈活性——可以在執行時動態決定需要呼叫什麼方法。

16、

1). 應用程式框架(applicationframeword)就是被設計用來解決某類特定問題的一個類或一組類。

2).要執行某個應用程式框架,通常是繼承一個或多個類,並覆蓋某個方法。

3).控制框架是一類特殊的應用程式框架,它用來解決響應事件的需求。

4).主要用來響應事件的系統被稱作事件驅動系統

以上內容整理自《Java程式設計思想》,若有遺漏,請您不吝指出!