欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

在Java中什么是內(nèi)部類

小編給大家分享一下在Java中什么是內(nèi)部類,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

創(chuàng)新互聯(lián)長期為上千客戶提供的網(wǎng)站建設服務,團隊從業(yè)經(jīng)驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為調(diào)兵山企業(yè)提供專業(yè)的成都網(wǎng)站制作、網(wǎng)站設計,調(diào)兵山網(wǎng)站改版等技術服務。擁有十載豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

前言

在Java中什么是內(nèi)部類

一、什么是內(nèi)部類?

在Java中,可以將一個類的定義放在另外一個類的定義內(nèi)部,這就是內(nèi)部類。內(nèi)部類本身就是類的一個屬性,與其他屬性 定義方式一致。

一個內(nèi)部類的例子:

public class Outer {   private int radius  = 1 ;  public static int count  = 2 ;        public Outer () {       }     class inner {   public void visitOuter () {     System.out.println( "visit outer private member variable:" + radius);     System.out.println( "visit outer static variable:" + count);    }       } }

二、內(nèi)部類的種類

內(nèi)部類可以分為四種:成員內(nèi)部類、局部內(nèi)部類、匿名內(nèi)部類和靜態(tài)內(nèi)部類。

在Java中什么是內(nèi)部類

靜態(tài)內(nèi)部類

定義在類內(nèi)部的靜態(tài)類,就是靜態(tài)內(nèi)部類。

 public class Outer {         private static int radius = 1;          static class StaticInner {           public void visit() {               System.out.println("visit outer static  variable:" + radius);           }       }  }

靜態(tài)內(nèi)部類可以訪問外部類所有的靜態(tài)變量,而不可訪問外部類的非靜態(tài)變量;靜態(tài)內(nèi)部類的創(chuàng)建方式, new外部類.靜態(tài)內(nèi)部類(),如下:

 Outer.StaticInner inner = new Outer.StaticInner();  inner.visit();

成員內(nèi)部類

定義在類內(nèi)部,成員位置上的非靜態(tài)類,就是成員內(nèi)部類。

 public class Outer {      private static  int radius = 1;     private int count =2;       class Inner {         public void visit() {             System.out.println("visit outer static  variable:" + radius);             System.out.println("visit outer   variable:" + count);        }    }  }

成員內(nèi)部類可以訪問外部類所有的變量和方法,包括靜態(tài)和非靜態(tài),私有和公有。成員內(nèi)部類依賴于外部類的實例,它的創(chuàng)建方式  外部類實例.new內(nèi)部類(),如下:

Outer outer = new Outer();  Outer.Inner inner = outer.new Inner();  inner.visit();

局部內(nèi)部類

定義在方法中的內(nèi)部類,就是局部內(nèi)部類。

public class Outer {     private  int out_a = 1;    private static int STATIC_b = 2;     public void testFunctionClass(){        int inner_c =3;        class Inner {           private void fun(){               System.out.println(out_a);               System.out.println(STATIC_b);               System.out.println(inner_c);           }       }       Inner  inner = new Inner();       inner.fun();    }    public static void testStaticFunctionClass(){       int d =3;        class Inner {           private void fun(){               // System.out.println(out_a); 編譯錯誤,定義在靜態(tài)方法中的局部類不可以訪問外部類的實例變量               System.out.println(STATIC_b);               System.out.println(d);           }        }       Inner  inner = new Inner();       inner.fun();    }  }

定義在實例方法中的局部類可以訪問外部類的所有變量和方法,定義在靜態(tài)方法中的局部類只能訪問外部類的靜態(tài)變量和方法。局部內(nèi)部類的創(chuàng)建方式,在對應方法內(nèi),  new內(nèi)部類(),如下:

public static void testStaticFunctionClass(){    class Inner {    }    Inner inner = new Inner(); }

匿名內(nèi)部類

匿名內(nèi)部類就是沒有名字的內(nèi)部類,日常開發(fā)中使用的比較多。

 public class Outer {          private void test(final int i) {           new Service() {               public void method() {                   for (int j = 0; j < i; j++) {                       System.out.println("匿名內(nèi)部類" );                   }               }          }.method();      }   }   //匿名內(nèi)部類必須繼承或?qū)崿F(xiàn)一個已有的接口   interface Service{      void method();  }

除了沒有名字,匿名內(nèi)部類還有以下特點:

  • 匿名內(nèi)部類必須繼承一個抽象類或者實現(xiàn)一個接口。

  • 匿名內(nèi)部類不能定義任何靜態(tài)成員和靜態(tài)方法。

  • 當所在的方法的形參需要被匿名內(nèi)部類使用時,必須聲明為 final。

  • 匿名內(nèi)部類不能是抽象的,它必須要實現(xiàn)繼承的類或者實現(xiàn)的接口的所有抽象方法。

匿名內(nèi)部類創(chuàng)建方式:

new 類/接口{    //匿名內(nèi)部類實現(xiàn)部分  }

三、內(nèi)部類的優(yōu)點

我們?yōu)槭裁匆褂脙?nèi)部類呢?因為它有以下優(yōu)點:

  • 一個內(nèi)部類對象可以訪問創(chuàng)建它的外部類對象的內(nèi)容,包括私有數(shù)據(jù)!

  • 內(nèi)部類不為同一包的其他類所見,具有很好的封裝性;

  • 內(nèi)部類有效實現(xiàn)了“多重繼承”,優(yōu)化 java 單繼承的缺陷。

  • 匿名內(nèi)部類可以很方便的定義回調(diào)。

一個內(nèi)部類對象可以訪問創(chuàng)建它的外部類對象的內(nèi)容,包括私有數(shù)據(jù)!

  public class Outer {        private  int radius = 1;         protected void test(){          System.out.println("我是外部類方法");      }        class Inner {         public void visit() {             System.out.println("訪問外部類變量" + radius);             test();         }     }  }

我們可以看到,內(nèi)部類Inner是可以訪問外部類Outer的私有變量radius或者方法test的。

內(nèi)部類不為同一包的其他類所見,具有很好的封裝性

當內(nèi)部類使用  private修飾時,這個類就對外隱藏了。當內(nèi)部類實現(xiàn)某個接口,并且進行向上轉(zhuǎn)型,對外部來說,接口的實現(xiàn)已經(jīng)隱藏起來了,很好體現(xiàn)了封裝性。

  //提供的接口   interface IContent{       String getContents();   }     public class Outer {       //私有內(nèi)部類屏蔽實現(xiàn)細節(jié)        private class PContents implements IContent{            @Override            public String getContents() {               System.out.println("獲取內(nèi)部類內(nèi)容");               return "內(nèi)部類內(nèi)容";           }       }        //對外提供方法      public IContent getIContent() {          return new PContents();      }        public static void main(String[] args) {          Outer outer=new Outer();          IContent a1=outer.getIContent();          a1.getContents();      }  }

我們可以發(fā)現(xiàn),Outer外部類對外提供方法getIContent,用內(nèi)部類實現(xiàn)細節(jié),再用private修飾內(nèi)部類,屏蔽起來,把Java的封裝性表現(xiàn)的淋漓盡致。

內(nèi)部類有效實現(xiàn)了“多重繼承”,優(yōu)化 java 單繼承的缺陷。

我們知道Java世界中,一個類只能有一個直接父類,即以單繼承方式存在。但是內(nèi)部類讓“多繼承”成為可能:

  • 一般來說,內(nèi)部類繼承某個類或者實現(xiàn)某個接口,內(nèi)部類的代碼操作創(chuàng)建它的外圍類的對象。內(nèi)部類提供了某種進入其外圍類的窗口。

  • 每個內(nèi)部類都可以隊里的繼承自一個(接口的)實現(xiàn),所以無論外圍類是否已經(jīng)繼承了某個(接口的)實現(xiàn),對于內(nèi)部類沒有影響

  • 接口解決了部分問題,一個類可以實現(xiàn)多個接口,內(nèi)部類允許繼承多個非接口類型(類或抽象類)。

一份來自Java編程思想,內(nèi)部類實現(xiàn)“多繼承”的溫暖如下:

class D {}  abstract class E{}  class Z extends D {  E makeE(){ return new E() {}; }  }  public class MultiImplementation {  static void takesD(D d) {}  static void takesE(E e) {}  public static void main(String[] args){  Z z = new Z();  takesD(z);  takesE(z.makeE());  }  }

代碼中出現(xiàn)了一個類D,一個抽象類E。然后,用類Z繼承D,內(nèi)部類構造返回E。因此,當你不管要的是D還是E,Z都可以應付,“多繼承”的特點完美表現(xiàn)出來。

匿名內(nèi)部類可以很方便的定義回調(diào)。

什么是回調(diào)?假設有兩個類A和B,在A中調(diào)用B的一個方法b,而b在執(zhí)行又調(diào)用了A的方法c,則c就稱為回調(diào)函數(shù)。

在Java中什么是內(nèi)部類

當然,回調(diào)函數(shù)也可以是a函數(shù),這就是同步回調(diào),最簡單的回調(diào)方式?;卣{(diào)應用場景挺多的,如android中的事件監(jiān)聽器。匿名內(nèi)部類可以很方便的定義回調(diào),看個例子

  //定義一個CallBack接口   public interface CallBack {       void execute();   }      public class TimeTools {          /**        * 測試函數(shù)調(diào)用時長,通過定義CallBack接口的execute方法       * @param callBack       */      public   void  testTime(CallBack callBack) {          long  beginTime = System.currentTimeMillis(); //記錄起始時間          callBack.execute(); ///進行回調(diào)操作          long  endTime = System.currentTimeMillis(); //記錄結(jié)束時間          System.out.println("[use time]:"  + (endTime - beginTime)); //打印使用時間      }        public   static   void  main(String[] args) {          TimeTools tool = new  TimeTools();          tool.testTime(new  CallBack(){              //匿名內(nèi)部類,定義execute方法              public   void  execute(){                  TestTimeObject testTimeObject = new TestTimeObject();                  testTimeObject.testMethod();              }          });      }  }

在調(diào)用testTime()測時間的時候,用匿名內(nèi)部類實現(xiàn)一個方法execute(),在該方法內(nèi)搞事情(執(zhí)行目標函數(shù)),執(zhí)行完后,又回到testTime方法,很好了實現(xiàn)測試函數(shù)調(diào)用時長的功能。顯然,匿名內(nèi)部類讓回調(diào)實現(xiàn)變得簡單。

四、內(nèi)部類的底層

內(nèi)部類標志符

每個內(nèi)部類都會產(chǎn)生一個.class文件,其中包含了如何創(chuàng)建該類型的對象的全部信息。內(nèi)部類也必須生成一個.class文件以包含它們的Class對象信息。內(nèi)部類文件的命名有嚴格規(guī)則:外圍類的名字+$+內(nèi)部類的名字。

一個簡單例子:

public class Outer {      class Inner{      }  }

javac Outer.java編譯完成后, 生成的class文件如下: 

在Java中什么是內(nèi)部類

如果內(nèi)部類是匿名的,編譯器會簡單地產(chǎn)生一個數(shù)字作為其標識符。如果內(nèi)部類是嵌套在別的內(nèi)部類之中(靜態(tài)內(nèi)部類),只需直接將它們的名字加在其外圍類標志符與“$”的后面。

為什么內(nèi)部類可以訪問外部類的成員,包括私有數(shù)據(jù)?

由上一小節(jié),我們知道內(nèi)部類可以訪問外部類的成員,包括私有數(shù)據(jù)。那么它是怎么做到的呢?接下來揭曉答案。

先看這個簡單地例子:

  public class Outer {          private int i = 0;         class Inner{           void method(){               System.out.println(i);           }       }  }

一個外部類Outer,一個外部類私有屬性i,一個內(nèi)部類Inner,一個內(nèi)部類方法method。內(nèi)部類方法訪問了外部類屬性i。

先編譯,javac Outer.java,生成.class文件,如下:

在Java中什么是內(nèi)部類

用命令 javap-classpath.-vOuter$Inner,反編譯Outter$Inner.class文件得到以下信息:

在Java中什么是內(nèi)部類

我們可以看到這一行,它是一個指向外部類對象的指針:

final innerclass.Outer this$0;

雖然編譯器在創(chuàng)建內(nèi)部類時為它加上了一個指向外部類的引用, 但是這個引用是怎樣賦值的呢?編譯器會為內(nèi)部類的構造方法添加一個參數(shù),進行初始化,  參數(shù)的類型就是外部類的類型,如下:

innerclass.Outer$Inner(innerclass.Outer);

成員內(nèi)部類中的Outter this&0 指針便指向了外部類對象,因此可以在成員內(nèi)部類中隨意訪問外部類的成員。

局部內(nèi)部類和匿名內(nèi)部類訪問局部變量的時候,為什么變量必須要加上final?

局部內(nèi)部類和匿名內(nèi)部類訪問局部變量的時候,為什么變量必須要加上final呢?它內(nèi)部原理是什么呢?

先看這段代碼:

  public class Outer {          void outMethod(){           final int a =10;           class Inner {               void innerMethod(){                   System.out.println(a);               }             }      }  }

反編譯(Outer$1Inner)得到以下信息:

在Java中什么是內(nèi)部類

我們在內(nèi)部類innerMethod方法中,可以看到以下這條指令:

3:bipush   10
  • 它表示將常量10壓入棧中,表示使用的是一個本地局部變量。

  • 其實,如果一個變量的值在編譯期間可以確定(demo中確定是10了),則編譯器會默認在匿名內(nèi)部類(局部內(nèi)部類)的常量池中添加一個內(nèi)容相等的字面量或直接將相應的字節(jié)碼嵌入到執(zhí)行字節(jié)碼中。

  • 醬紫可以確保局部內(nèi)部類使用的變量與外層的局部變量區(qū)分開,它們只是值相等而已。

以上例子,為什么要加final呢?是因為生命周期不一致,  局部變量直接存儲在棧中,當方法執(zhí)行結(jié)束后,非final的局部變量就被銷毀。而局部內(nèi)部類對局部變量的引用依然存在,如果局部內(nèi)部類要調(diào)用局部變量時,就會出錯。加了final,可以確保局部內(nèi)部類使用的變量與外層的局部變量區(qū)分開,解決了這個問題。

我們再來看一段代碼,其實就是把變量a挪到傳參方式進來。

  public class Outer {          void outMethod(final int a){           class Inner {               void innerMethod(){                   System.out.println(a);               }           }       }  }

反編譯可得:

在Java中什么是內(nèi)部類

我們看到匿名內(nèi)部類Outer$1Inner的構造器含有兩個參數(shù),一個是指向外部類對象的引用,一個是int型變量,很顯然,這里是將變量innerMethod方法中的形參a以參數(shù)的形式傳進來對匿名內(nèi)部類中的拷貝(變量a的拷貝)進行賦值初始化。

那么,新的問題又來了,既然在innerMethod方法中訪問的變量a和outMethod方法中的變量a不是同一個變量,當在innerMethod方法中修改a會怎樣?那就會造成數(shù)據(jù)不一致的問題了。

怎么解決呢?使用final修飾符,final修飾的引用類型變量,不允許指向新的對象,這就解決數(shù)據(jù)不一致問題。注意: 在Java8  中,被局部內(nèi)部類引用的局部變量,默認添加final,所以不需要添加final關鍵詞。

五、內(nèi)部類的應用場景。

一般我們在哪些場景下使用內(nèi)部類呢?

場景之一:一些多算法場合

一些算法多的場合,也可以借助內(nèi)部類,如:

  Arrays.sort(emps,new Comparator(){     Public int compare(Object o1,Object o2)     {      return ((Employee)o1).getServedYears()-((Employee)o2).getServedYears();     }   });

場景二:解決一些非面向?qū)ο蟮恼Z句塊。

如果一些語句塊,包括if&hellip;else語句,case語句等等比較多,不好維護擴展,那么就可以借助內(nèi)部類+設計模式解決。

場景之三:適當使用內(nèi)部類,使得代碼更加靈活和富有擴展性。

適當?shù)氖褂脙?nèi)部類,可以使得你的代碼更加靈活和富有擴展性。如JDK的lamda表達式,用內(nèi)部類非常多,代碼優(yōu)雅很多。如下:

// JDK8 Lambda表達式寫法  new Thread(() -> System.out.println("Thread run()")).start();

場景四:當某個類除了它的外部類,不再被其他的類使用時。

如果一個類,不能為其他的類使用;或者出于某種原因,不能被其他類引用。那我們就可以考慮把它實現(xiàn)為內(nèi)部類。數(shù)據(jù)庫連接池就是這樣一個典型例子。

六、內(nèi)部類常見面試題

最后,我們來看一道經(jīng)典內(nèi)部類面試題吧。

  public class Outer {       private int age = 12;          class Inner {           private int age = 13;           public void print() {               int age = 14;               System.out.println("局部變量:" + age);               System.out.println("內(nèi)部類變量:" + this.age);              System.out.println("外部類變量:" + Outer.this.age);          }      }       public static void main(String[] args) {          Outer.Inner in = new Outer().new Inner();          in.print();      }    }

運行結(jié)果:

在Java中什么是內(nèi)部類

以上是“在Java中什么是內(nèi)部類”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

分享名稱:在Java中什么是內(nèi)部類
文章分享:http://chinadenli.net/article12/ppccgc.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導航品牌網(wǎng)站建設、網(wǎng)站排名、外貿(mào)建站搜索引擎優(yōu)化、網(wǎng)站設計

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁設計
av在线免费观看在线免费观看| 日本午夜免费啪视频在线| 国产精品成人一区二区三区夜夜夜| 国产一区二区精品高清免费 | 不卡一区二区高清视频| 亚洲精品国产第一区二区多人| 九九热这里只有免费精品| 欧美日韩亚洲精品内裤| 欧美夫妻性生活一区二区| 亚洲国产av一二三区| 国产精品日本女优在线观看| 欧美三级不卡在线观线看| 国产三级视频不卡在线观看| 91欧美激情在线视频| 少妇福利视频一区二区| 久久精品少妇内射毛片| 99精品国产一区二区青青| 日韩欧美黄色一级视频| 日韩欧美综合中文字幕| 精品al亚洲麻豆一区| 又色又爽又无遮挡的视频| 国产永久免费高清在线精品| 精品国产丝袜一区二区| 国产精品福利一级久久| 丰满人妻一二区二区三区av| 日韩欧美第一页在线观看| 日韩免费国产91在线| 亚洲欧洲精品一区二区三区| 亚洲免费黄色高清在线观看| 国产成人av在线免播放观看av| 亚洲国产一级片在线观看| 精品少妇一区二区三区四区| 国产精品免费自拍视频| 久久中文字幕中文字幕中文| 久热久热精品视频在线观看| 九九热最新视频免费观看| 98精品永久免费视频| 人妻内射精品一区二区| 国产精品一区欧美二区| 精品国自产拍天天青青草原| 成人精品一级特黄大片|