1. 程式人生 > >【JAVA】的內部類詳解

【JAVA】的內部類詳解

轉載部落格: https://www.cnblogs.com/dolphin0520/p/3811445.html
作者:海 子

  說起內部類這個詞,想必很多人都不陌生,但是又會覺得不熟悉。原因是平時編寫程式碼時可能用到的場景不多,用得最多的是在有事件監聽的情況下,並且即使用到也很少去總結內部類的用法。今天我們就來一探究竟。下面是本文的目錄大綱:

  一.內部類基礎

  二.深入理解內部類

  三.內部類的使用場景和好處

  四.常見的與內部類相關的筆試面試題

  若有不正之處,請多諒解並歡迎批評指正。

  請尊重作者勞動成果,轉載請標明原文連結:

  http://www.cnblogs.com/dolphin0520/p/3811445.html

一.內部類基礎

  在Java中,可以將一個類定義在另一個類裡面或者一個方法裡面,這樣的類稱為內部類。廣泛意義上的內部類一般來說包括這四種:成員內部類、區域性內部類、匿名內部類和靜態內部類。下面就先來了解一下這四種內部類的用法。

  1.成員內部類

  成員內部類是最普通的內部類,它的定義為位於另一個類的內部,形如下面的形式:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 class Circle {      double radius = 0 ;            public
Circle( double radius) {          this .radius = radius;      }            class Draw {     //內部類          public void drawSahpe() {              System.out.println( "drawshape" );          }      } }

  這樣看起來,類Draw像是類Circle的一個成員,Circle稱為外部類。成員內部類可以無條件訪問外部類的所有成員屬性和成員方法(包括private成員和靜態成員)。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Circle {      private double radius = 0 ;      public static int count = 1 ;      public Circle( double radius) {          this .radius = radius;      }            class Draw {     //內部類          public void drawSahpe() {              System.out.println(radius);  //外部類的private成員              System.out.println(count);   //外部類的靜態成員          }      } }

  不過要注意的是,當成員內部類擁有和外部類同名的成員變數或者方法時,會發生隱藏現象,即預設情況下訪問的是成員內部類的成員。如果要訪問外部類的同名成員,需要以下面的形式進行訪問:

?
1 2 外部類. this .成員變數 外部類. this .成員方法

  雖然成員內部類可以無條件地訪問外部類的成員,而外部類想訪問成員內部類的成員卻不是這麼隨心所欲了。在外部類中如果要訪問成員內部類的成員,必須先建立一個成員內部類的物件,再通過指向這個物件的引用來訪問:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Circle {      private double radius = 0 ;        public Circle( double radius) {          this .radius = radius;          getDrawInstance().drawSahpe();   //必須先建立成員內部類的物件,再進行訪問      }            private Draw getDrawInstance() {          return new Draw();      }            class Draw {     //內部類          public void drawSahpe() {              System.out.println(radius);  //外部類的private成員          }      } }

  成員內部類是依附外部類而存在的,也就是說,如果要建立成員內部類的物件,前提是必須存在一個外部類的物件。建立成員內部類物件的一般方式如下:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class Test {      public static void main(String[] args)  {          //第一種方式:          Outter outter = new Outter();          Outter.Inner inner = outter. new Inner();  //必須通過Outter物件來建立                    //第二種方式:          Outter.Inner inner1 = outter.getInnerInstance();      } }   class Outter {      private Inner inner = null ;      public Outter() {                }            public Inner getInnerInstance() {          if (inner == null )              inner = new Inner();          return inner;      }             class Inner {          public Inner() {                        }      } }

  內部類可以擁有private訪問許可權、protected訪問許可權、public訪問許可權及包訪問許可權。比如上面的例子,如果成員內部類Inner用private修飾,則只能在外部類的內部訪問,如果用public修飾,則任何地方都能訪問;如果用protected修飾,則只能在同一個包下或者繼承外部類的情況下訪問;如果是預設訪問許可權,則只能在同一個包下訪問。這一點和外部類有一點不一樣,外部類只能被public和包訪問兩種許可權修飾。我個人是這麼理解的,由於成員內部類看起來像是外部類的一個成員,所以可以像類的成員一樣擁有多種許可權修飾。

  2.區域性內部類

  區域性內部類是定義在一個方法或者一個作用域裡面的類,它和成員內部類的區別在於區域性內部類的訪問僅限於方法內或者該作用域內。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class People{      public People() {                } }   class Man{      public Man(){                }            public People getWoman(){          class Woman extends People{   //區域性內部類              int age = 0 ;          }          return new Woman();      } }

  注意,區域性內部類就像是方法裡面的一個區域性變數一樣,是不能有public、protected、private以及static修飾符的。

  3.匿名內部類

  匿名內部類應該是平時我們編寫程式碼時用得最多的,在編寫事件監聽的程式碼時使用匿名內部類不但方便,而且使程式碼更加容易維護。下面這段程式碼是一段Android事件監聽程式碼:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 scan_bt.setOnClickListener( new OnClickListener() {                            @Override              public void onClick(View v) {                  // TODO Auto-generated method stub                                }          });                    history_bt.setOnClickListener( new OnClickListener() {                            @Override              public void onClick(View v) {                  // TODO Auto-generated method stub                                }          });

  這段程式碼為兩個按鈕設定監聽器,這裡面就使用了匿名內部類。這段程式碼中的:

?
1 2 3 4 5 6 7 8 new OnClickListener() {                            @Override              public void onClick(View v) {                  // TODO Auto-generated method stub                                }          }

  就是匿名內部類的使用。程式碼中需要給按鈕設定監聽器物件,使用匿名內部類能夠在實現父類或者介面中的方法情況下同時產生一個相應的物件,但是前提是這個父類或者介面必須先存在才能這樣使用。當然像下面這種寫法也是可以的,跟上面使用匿名內部類達到效果相同。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private void setListener() {      scan_bt.setOnClickListener( new Listener1());             history_bt.setOnClickListener( new Listener2()); }   class Listener1 implements View.OnClickListener{      @Override      public void onClick(View v) {      // TODO Auto-generated method stub                    } }   class Listener2 implements View.OnClickListener{      @Override      public void onClick(View v) {      // TODO Auto-generated method stub                    } }

  這種寫法雖然能達到一樣的效果,但是既冗長又難以維護,所以一般使用匿名內部類的方法來編寫事件監聽程式碼。同樣的,匿名內部類也是不能有訪問修飾符和static修飾符的。

  匿名內部類是唯一一種沒有構造器的類。正因為其沒有構造器,所以匿名內部類的使用範圍非常有限,大部分匿名內部類用於介面回撥。匿名內部類在編譯的時候由系統自動起名為Outter$1.class。一般來說,匿名內部類用於繼承其他類或是實現介面,並不需要增加額外的方法,只是對繼承方法的實現或是重寫。

  4.靜態內部類

  靜態內部類也是定義在另一個類裡面的類,只不過在類的前面多了一個關鍵字static。靜態內部類是不需要依賴於外部類的,這點和類的靜態成員屬性有點類似,並且它不能使用外部類的非static成員變數或者方法,這點很好理解,因為在沒有外部類的物件的情況下,可以建立靜態內部類的物件,如果允許訪問外部類的非static成員就會產生矛盾,因為外部類的非static成員必須依附於具體的物件。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Test {      public static void main(String[] args)  {          Outter.Inner inner = new Outter.Inner();      } }   class Outter {      public Outter() {                }            static class Inner {          public Inner() {                        }      } }

  

二.深入理解內部類

  1.為什麼成員內部類可以無條件訪問外部類的成員?

  在此之前,我們已經討論過了成員內部類可以無條件訪問外部類的成員,那具體究竟是如何實現的呢?下面通過反編譯位元組碼檔案看看究竟。事實上,編譯器在進行編譯的時候,會將成員內部類單獨編譯成一個位元組碼檔案,下面是Outter.java的程式碼:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Outter {      private Inner inner = null ;      public Outter() {                }            public Inner getInnerInstance() {          if (inner == null )              inner = new Inner();          return inner;      }             protected class Inner {          public Inner() {                        }      } }

  編譯之後,出現了兩個位元組碼檔案:

  反編譯Outter$Inner.class檔案得到下面資訊:

?
1 2 3 4 5 6 7 8 9 10 11 12

相關推薦

java部類例子

1.內部類是在類的內部定義的類 2.內部類分為成員內部類,區域性內部類,匿名內部類。 3.內部類中可以直接呼叫其所在類的私有變數以及方法,但是外部類不可以呼叫內部類的成員。 4.內部類的例項一定要繫結

Java部類(Inner Class)如何建立(new)

簡單來說,內部類(inner class)指那些類定義程式碼被置於其它類定義中的類;而對於一般的、類定義程式碼不巢狀在其它類定義中的類,稱為頂層(top-level)類。對於一個內部類,包含其定義

[JAVA基礎]部類

public class OuterClass { private String sex; public static String name = "chenssy"; /** *靜態內部類 */ static class InnerClass

Java記憶體機制(new操作的執行原理)

1.Java的記憶體機制  Java 把記憶體劃分成兩種:一種是棧記憶體,另一種是堆記憶體。在函式中定義的一些基本型別的變數和物件的引用變數都是在函式的棧記憶體中分配,當在一段程式碼塊定義一個變數時,Java 就在棧中為這個變數分配記憶體空間,當超過變數的作用域後(比如,在函式A中呼叫函式B,在函式B中定義變

java匿名部類

【宣告】此文轉載自:http://blog.csdn.net/zhandoushi1982/article/details/8778487 ——感謝分享,尊重作者,交流無限! 記得JAVA中抽象類是不能建立例項的,但是在程式碼中總會看見new 抽象類名的用法。如

JAVA部類

轉載部落格: https://www.cnblogs.com/dolphin0520/p/3811445.html 作者:海 子   說起內部類這個詞,想必很多人都不陌生,但是又會覺得不熟悉。原因是平時編寫程式碼時可能用到的場景不多

Java部類

一、內部類基礎   在Java中,可以將一個類定義在另一個類裡面或者一個方法裡面,這樣的類稱為內部類。廣泛意義上的內部類一般來說包括這四種:成員內部類、區域性內部類、匿名內部類和靜態內部類。下面就先來了解一下這四種內部類的用法。     1、成員內部類   成員內部類是最普通的內部類,它的定

Java部類

strong 匿名 per 創建 show rac 成員變量 end outer 成員內部類(聲明在類內部且方法外的):1是外部類的一個成員:①可以有修飾符(4個)②static final ③可以調用外部類的屬性、方法

Java筆記之內部類、匿名部類

內部類 內部類訪問特點: 1、內部類可以直接訪問外部類中的成員 2、外部類要訪問內部類,必須建立內部類的物件 class Outer { private int num=3; class Inner //內部類 { void s

“全棧2019”Java第七十七章:抽象部類與抽象靜態部類

難度 初級 學習時間 10分鐘 適合人群 零基礎 開發語言 Java 開發環境 JDK v11 IntelliJ IDEA v2018.3 文章原文連結 “全棧2019”Java第七十七章:抽象內部類與抽象靜態內部類詳解 下一章 “全棧2019”Java第七十八章:內部

java四種部類

一般來說,有4中內部類:常規內部類、靜態內部類、區域性內部類、匿名內部類。  一.常規內部類:常規內部類沒有用static修飾且定義在在外部類類體中。   1.常規內部類中的方法可以直接使用外部類的例項變數和例項方法。   2.在常規內部類中可以直接用內部類建立物件  

Java中的部類,為什麼需要部類

內部類的共性   內部類分為: 成員內部類、靜態巢狀類、方法內部類、匿名內部類。      (1)、內部類仍然是一個獨立的類,在編譯之後內部類會被編譯成獨立的.class檔案,但是前面冠以外部類的類

Java部類 及 區域性部類和匿名部類只能訪問區域性final變數的原因

說起內部類這個詞,想必很多人都不陌生,但是又會覺得不熟悉。原因是平時編寫程式碼時可能用到的場景不多,用得最多的是在有事件監聽的情況下,並且即使用到也很少去總結內部類的用法。今天我們就來一探究竟。下面是本文的目錄大綱:   一.內部類基礎   二.深入理解內部類   三.內部類的使用場景和好處   

Java面試題-匿名部類

前言 匿名內部類應該是屬於java基礎的知識點,後來我們在開發中使用的也不算很少了,只是我們可能沒太注意自己所建立的或者使用的一些類就是匿名內部類,我看了排名很靠前的一些關於匿名內部類的一些 部落格講解的都很棒,只可惜跳躍的很大導致很多人不多看幾次很難理

java部類(1):java部類的建立以及對外提供的訪問方式,匿名部類

前言 我們在描述事物的時候,事物的內部還有事物,這個內部事物還要訪問外部事物中的內容時。那麼,這個內部事物就可以用內部類來描述。內部類也叫內建類,巢狀類。 正文 一,內部類的形式以及對外訪問的方式 顧名思義,內部類就是一個類巢狀在另一個類中。內部類可

Java 部類及其練習

學習心得 一、專業課 1、內部類 1.內部類 1.1 是指在一個外部類的內部再定義一個類,類名不需要和文件夾相同 1.2內部類可以是靜態static的,也可用public,default,protected和private修飾(而外部類只能使用 public和default

“全棧2019”Java第七十三章:外部類裡多個靜態非靜態部類

難度 初級 學習時間 10分鐘 適合人群 零基礎 開發語言 Java 開發環境 JDK v11 IntelliJ IDEA v2018.3 文章原文連結 “全棧2019”Java第七十三章:外部類裡多個靜態非靜態內部類詳解

“全棧2019”Java第九十四章:區域性部類

難度 初級 學習時間 10分鐘 適合人群 零基礎 開發語言 Java 開發環境 JDK v11 IntelliJ IDEA v2018.3 文章原文連結 “全棧2019”Java第九十四章:區域性內部類詳解 下一章 “全棧2019”Java第九十五章:方法中可以定義靜態

java 網路程式設計10 HTTP協議

【1】http協議概念,http1.0與http1.1 區別: 1.http(Hypertext Transfer Protocol)超文字轉出協議,從1990年開始就在www上廣泛應用。HTTP是一個屬於應用層的面向物件的協議,由於其簡捷、快速的方式,適用於分散式超媒體資

Java之匿名部類

表示 div -h UNC 花括號 繼承 匿名對象 對象 但是 前言 本文講解Java中最後一種內部類,叫做匿名內部類。顧名思義,所謂的匿名內部類就是一個沒有顯式的名字的內部類,在實際開發中,此種內部類用的是非常多的。 匿名內部類 本質:匿名內部類會隱式的繼承一個類或