Think in Java 第十章(內(nèi)部類)

信仰

一個(gè)類的定義放在另一個(gè)定義內(nèi)部,這就是內(nèi)部類。

10.1 創(chuàng)建內(nèi)部類
public class Parcel1{
 class Contents{
     private int i = 11;
     public int value (){ return i; }
 }
 class Destination {
     private String able;
     Destinaltion(String whereTo){
     label = whereTo;
  } 
     String readLabel (){ return label;} 
}
 public void ship(String dest){
     Contents c = new Contents();
     Destination d = new  Destination(dest);
     System.out.println(d.readLabel);
}
  public static void main(String[] args){
    Parcel1 p = new Parcel1();
    p.ship("Tasmainaaaaa");
 }
}

10.2 鏈接到外部類

內(nèi)部類是一種名字隱藏和組織代碼的模式,當(dāng)生成內(nèi)部類對(duì)象時(shí),此對(duì)象可以用訪問(wèn)外圍對(duì)象的所有成員


10.3 使用 .this與。new

對(duì)外部類的引用:外部類的名字緊跟this.
創(chuàng)建內(nèi)部類對(duì)象:使用 .new語(yǔ)法


10.4 內(nèi)部類與向上轉(zhuǎn)型

內(nèi)部類向上轉(zhuǎn)型為基類或一個(gè)接口,所得到的是指向基類或接口的引用,隱藏實(shí)現(xiàn)細(xì)節(jié)

public interface Destination{
  String readLabel();
}
public interface Contents{
   int value();
}
//(接口的所有成員自動(dòng)被設(shè)置成public)
class Parcel4{
    private class Pcontents implements Contenets {
      private int i =1;
      public int value(){return i;}
   }
   protected class PDestination implements Destination{
      private String label;
      private PDestination(String whereTo){ label = whereTo;}
      public String readLabel(){return label;}
   }
   public Destination destination(String s){
       return new PDestinations(s);
   }
   public Contents contents(){
       return new PContents();
  }
}
public class TestPracel{
   public static void main(String[] args){
      Pracel4 p = new Parcel4();
      Contents c = p.contents();
      Destriation d =  p.destination("tasmainaaa");
 }

內(nèi)部類PContents是privae,只有Parcel4 可以訪問(wèn), PDesination是protected只有Parcel4及子類可以訪問(wèn)
private內(nèi)部類可以阻止任何依賴型的代碼,隱藏實(shí)現(xiàn)細(xì)節(jié)。


10.5 在方法和作用域內(nèi)的內(nèi)部類

可以在方法或在作用域定義內(nèi)部類。
理由

  • 1 實(shí)現(xiàn)某種類型的接口,可以創(chuàng)建并返回對(duì)其引用。
  • 2 創(chuàng)建一個(gè)類來(lái)輔助解決方案,但不希望這個(gè)類時(shí)公用的。

內(nèi)部類的實(shí)現(xiàn)。

  • 1> 定義在方法中的內(nèi)部類
  • 2>定義在作用域內(nèi)的類,作用域的方法在內(nèi)部
  • 3>一個(gè)實(shí)現(xiàn)接口的匿名類
  • 4>一個(gè)匿名類,它擴(kuò)展了默認(rèn)構(gòu)造器的類
  • 5>一個(gè)匿名類,它執(zhí)行字段初始化
  • 6>一個(gè)匿名類,它通過(guò)實(shí)例初始化實(shí)現(xiàn)構(gòu)造(匿名類不可能有構(gòu)造器)

10.6 匿名內(nèi)部類
public class Parcel7{
   public Contents contents(){
       return new Contents(){
           private int i =11;
           public int value(){return i;}
     };
   }
    public static void main(String[] args){
     Parcel7 p = new Parcel7();
     Contents c = p.contents();
  }
}

匿名內(nèi)部類末尾的分號(hào),并不是用來(lái)標(biāo)記內(nèi)部類的結(jié)束,標(biāo)記的是表達(dá)式的結(jié)束,這個(gè)表達(dá)式包含了匿名內(nèi)部類。

匿名內(nèi)部類使用外部對(duì)象(不包含基類使用)參數(shù)引用需要final修飾。
匿名內(nèi)部類實(shí)例初始化的效果就是構(gòu)造器,但受到了限制(不能重載實(shí)例初始化方法,匿名內(nèi)部類可以擴(kuò)展類,也可以實(shí)現(xiàn)接口,但不能兩者兼?zhèn)?,如果是?shí)現(xiàn)接口也只能實(shí)現(xiàn)一個(gè)接口)

  • 10.6.1 再訪工廠方法
interface Service{
    void method1();
    void method2();
}
interface ServiceFactory{
     Service getService();
}
class Implementation1 implement Service{
      private Implementation1(){}
      public method1(){ print("Implementation1 method1")}
      public method2(){ print("Implementation1 method2")}
}
  public static ServiceFactory factory = 
       new ServiceFactory(){
           public Service getService(){
             return new Implementation1 (); 
  };
}
class Implementation2 implement Service{
      private Implementation2(){}
      public method1(){ print("Implementation2 method1")}
      public method2(){ print("Implementation2 method2")}
}
  public static ServiceFactory factory = 
      new ServiceFactory(){
          public Service getService(){
           return new Implementation2 (); 
  };
}
 public class Factories{
   public static void ServiceConsumer(ServiceFactory factory){
        Service s = factory.getService();
        s.method1();
        s.method2();
   }
   public static void main(String[] args){
        ServiceConsumer(Implementation1.factory);
        ServiceConsumer(Implementation2.factory);
   }
 }

由上構(gòu)造器都可以是private,并沒(méi)有創(chuàng)建工廠的類具名

優(yōu)先使用類而不是接口。如果你的設(shè)計(jì)需要接口,你必須了解它。否則,不到迫不得已,不需要將它放到你的設(shè)計(jì)中


10.7 嵌套類

如果不需要內(nèi)部類對(duì)象與外圍類有聯(lián)系,可以將內(nèi)部類對(duì)象聲明為static,這就是嵌套類。
普通內(nèi)部類對(duì)象隱式保存了一個(gè)引用,指向創(chuàng)建它的外圍類對(duì)象,而內(nèi)部類是static時(shí),嵌套類就意味著

  • 1 要?jiǎng)?chuàng)建嵌套類的對(duì)象,并不需要外圍類對(duì)象。
  • 2 不能從嵌套類對(duì)象中訪問(wèn)費(fèi)靜態(tài)的外圍類對(duì)象
    (注意普通類內(nèi)部不能有static數(shù)據(jù)和static字段,也不能包含嵌套類,但嵌套類可以包含這些東西)

10.8 為什么需要內(nèi)部類

Sun公司為什么會(huì)增加這個(gè)語(yǔ)言特性,一般來(lái)說(shuō),內(nèi)部類繼承某個(gè)類或?qū)崿F(xiàn)某個(gè)接口,內(nèi)部類的代碼操作創(chuàng)建它的外圍類的對(duì)象,內(nèi)部類提供了某種進(jìn)入外圍類的窗口。

  • 1) 如果只是需要一個(gè)接口的引用,為什么不通過(guò)外圍類實(shí)現(xiàn)那個(gè)接口
    答案是:“如果這能滿足需求,那么就應(yīng)該這樣做”
  • 2) 內(nèi)部類實(shí)現(xiàn)一個(gè)接口與外圍類實(shí)現(xiàn)這個(gè)接口有什么區(qū)別
    答案是:后者不是總能享用到接口帶來(lái)的方便,有時(shí)需要用到接口的實(shí)現(xiàn),所以使用最吸引人的原因是:
    每個(gè)內(nèi)部類都能獨(dú)立繼承一個(gè)接口的實(shí)現(xiàn),所以無(wú)論外圍類是否已經(jīng)繼承了某個(gè)接口的實(shí)現(xiàn),對(duì)于內(nèi)部類都沒(méi)有影響

也就是說(shuō)內(nèi)部類允許繼承多個(gè)非接口類型

內(nèi)部類可以獲得其他一些特性

  • 1)內(nèi)部類可以有多個(gè)實(shí)例,每個(gè)實(shí)例都有自己的狀態(tài)信息,并且與外圍類的對(duì)象信息相互獨(dú)立。

  • 2)在單個(gè)外圍類中,可以讓內(nèi)部類以不同的方式實(shí)現(xiàn)同一個(gè)接口,或繼承同一個(gè)類。

  • 3)創(chuàng)建內(nèi)部類對(duì)象不依賴外圍類對(duì)象的創(chuàng)建。

  • 4)內(nèi)部類沒(méi)有“is-a”關(guān)系,他就是一個(gè)獨(dú)立的類

  • 10.8.1 閉包與回調(diào)
    通過(guò)內(nèi)部類提供的閉包功能是優(yōu)良的解決方案,它比指針更靈活,更安全。


10.9 內(nèi)部類的繼承

內(nèi)部類的構(gòu)造器不需連接到指向外圍類對(duì)象的引用,所以在繼承內(nèi)部類的時(shí)候,事情會(huì)變得有點(diǎn)復(fù)雜,問(wèn)題在于,那個(gè)指向外圍類的對(duì)象的“秘密的”引用必須被初始化,而在導(dǎo)出類中不再存在可連接的默認(rèn)對(duì)象。要解決這個(gè)問(wèn)題,必須使用特殊的語(yǔ)法說(shuō)明它們之間的關(guān)聯(lián)。

class WithInner{
  class Inner{}
}
public class InheritInner extends WithInner.Inner{
InheritInner(WithInner wi){}
   wi.super();
}
public static void main(String[] args){
   WithInner wi = new WitnInner();
   InherItInner ii = new InheritInner(wi);
  }
}

10.10 內(nèi)部類可以被覆蓋嗎

覆蓋內(nèi)部類就好像是它的一個(gè)方法,其實(shí)并不起什么作用


10.11 局部?jī)?nèi)部類

可以訪問(wèn)當(dāng)前代碼塊內(nèi)的常量,以及此外圍類所有成員。
匿名內(nèi)部類和局部?jī)?nèi)部類創(chuàng)建的比較

interface Counter{
  int next();
}
public class LocalInnerClass{
    private int count = 0;
    Counter getCounter(final String name){
       class LocalCounter implements Counter{
           public LocalCounter(){}
           public int next(){ 
           return   count++;              
      }
    }
  }

Counter getCounter2(final String name){
   return new Counter(){
           public int next(){
             return count++; 
         }
     };
  }
}

當(dāng)需要一個(gè)已命名的構(gòu)造器,或者需要重載構(gòu)造器,使用局部?jī)?nèi)部類,匿名內(nèi)部類只能用于實(shí)例初始化。
當(dāng)需要不止一個(gè)內(nèi)部類對(duì)象時(shí),使用局部?jī)?nèi)部類。


10.12 內(nèi)部類標(biāo)識(shí)符

每個(gè)類都會(huì)產(chǎn)生一個(gè).class文件,其中包含了如何創(chuàng)建該類型的全部信息(此信息產(chǎn)生一個(gè)“meta-class”,叫Class對(duì)象)內(nèi)部類必須生成一個(gè).class文件以包含它們的Class對(duì)象信息。這些文件的命名有嚴(yán)格的規(guī)定:外圍類的名字,加上“$”再加上內(nèi)部類的名字

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容