標籤:
Java 內部類種類及使用解析內部類Inner Class
將相關的類組織在一起,從而降低了命名空間的混亂。
一個內部類可以定義在另一個類裡,可以定義在函數裡,甚至可以作為一個運算式的一部分。
Java中的內部類共分為四種:
靜態內部類static inner class (also called nested class)
成員內部類member inner class
局部內部類local inner class
匿名內部類anonymous inner class
靜態內部類Static Inner Class
最簡單的內部類形式。
類定義時加上static關鍵字。
不能和外部類有相同的名字。
被編譯成一個完全獨立的.class檔案,名稱為OuterClass$InnerClass.class的形式。
只可以訪問外部類的靜態成員和靜態方法,包括了私人的靜態成員和方法。
產生靜態內部類對象的方式為:
OuterClass.InnerClass inner = new OuterClass.InnerClass();
靜態內部類使用代碼:
package com.learnjava.innerclass;class StaticInner{ private static int a = 4; // 靜態內部類 public static class Inner { public void test() { // 靜態內部類可以訪問外部類的靜態成員 // 並且它只能訪問靜態 System.out.println(a); } }}public class StaticInnerClassTest{ public static void main(String[] args) { StaticInner.Inner inner = new StaticInner.Inner(); inner.test(); }}
成員內部類Member Inner Class
成員內部類也是定義在另一個類中,但是定義時不用static修飾。
成員內部類和靜態內部類可以類比為非靜態成員變數和靜態成員變數。
成員內部類就像一個執行個體變數。
它可以訪問它的外部類的所有成員變數和方法,不管是靜態還是非靜態都可以。
在外部類裡面建立成員內部類的執行個體:
this.new Innerclass();
在外部類之外建立內部類的執行個體:
(new Outerclass()).new Innerclass();
在內部類裡訪問外部類的成員:
Outerclass.this.member
詳情見代碼例子:
package com.learnjava.innerclass;class MemberInner{ private int d = 1; private int a = 2; // 定義一個成員內部類 public class Inner2 { private int a = 8; public void doSomething() { // 直接存取外部類對象 System.out.println(d); System.out.println(a);// 直接存取a,則訪問的是內部類裡的a // 如何訪問到外部類裡的a呢? System.out.println(MemberInner.this.a); } }}public class MemberInnerClassTest{ public static void main(String[] args) { // 建立成員內部類的對象 // 需要先建立外部類的執行個體 MemberInner.Inner2 inner = new MemberInner().new Inner2(); inner.doSomething(); }}
局部內部類Local Inner Class
局部內部類定義在方法中,比方法的範圍還小。是內部類中最少用到的一種類型。
像局部變數一樣,不能被public, protected, private和static修飾。
只能存取方法中定義的final類型的局部變數。
局部內部類在方法中定義,所以只能在方法中使用,即只能在方法當中產生局部內部類的執行個體並且調用其方法。
package com.learnjava.innerclass;class LocalInner{ int a = 1; public void doSomething() { int b = 2; final int c = 3; // 定義一個局部內部類 class Inner3 { public void test() { System.out.println("Hello World"); System.out.println(a); // 不可以訪問非final的局部變數 // error: Cannot refer to a non-final variable b inside an inner // class defined in a different method // System.out.println(b); // 可以訪問final變數 System.out.println(c); } } // 建立局部內部類的執行個體並調用方法 new Inner3().test(); }}public class LocalInnerClassTest{ public static void main(String[] args) { // 建立外部類對象 LocalInner inner = new LocalInner(); // 調用外部類的方法 inner.doSomething(); }}
匿名內部類Anonymous Inner Class
匿名內部類就是沒有名字的局部內部類,不使用關鍵字class, extends, implements, 沒有構造方法。
匿名內部類隱式地繼承了一個父類或者實現了一個介面。
匿名內部類使用得比較多,通常是作為一個方法參數。
package com.learnjava.innerclass;import java.util.Date;public class AnonymouseInnerClass{ @SuppressWarnings("deprecation") public String getDate(Date date) { return date.toLocaleString(); } public static void main(String[] args) { AnonymouseInnerClass test = new AnonymouseInnerClass(); // 列印日期: String str = test.getDate(new Date()); System.out.println(str); System.out.println("----------------"); // 使用匿名內部類 String str2 = test.getDate(new Date() { });// 使用了花括弧,但是不填入內容,執行結果和上面的完全一致 // 產生了一個繼承了Date類的子類的對象 System.out.println(str2); System.out.println("----------------"); // 使用匿名內部類,並且重寫父類中的方法 String str3 = test.getDate(new Date() { // 重寫父類中的方法 @Override @Deprecated public String toLocaleString() { return "Hello: " + super.toLocaleString(); } }); System.out.println(str3); }}
產生的.class檔案中,匿名類會產生OuterClass$1.class檔案,數字根據是第幾個匿名類而類推。
Swing中使用內部類的例子如下:
package com.learnjava.innerclass;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import javax.swing.JButton;import javax.swing.JFrame;public class SwingTest{ public static void main(String[] args) { JFrame frame = new JFrame("JFrame"); JButton button = new JButton("JButton"); button.addActionListener(new ActionListener() { // new出來一個實現了ActionListener介面的類的執行個體 @Override public void actionPerformed(ActionEvent arg0) { System.out.println("Hello World"); } }); //加入按鈕 frame.getContentPane().add(button); //設定關閉行為 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(200, 200); frame.addWindowListener(new WindowAdapter() { //也可以使用繼承了適配器類的匿名內部類 @Override public void windowClosing(WindowEvent e) { System.out.println("Closing"); System.exit(0); } }); frame.setVisible(true); }}
【轉】Java 內部類種類及使用解析