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();
靜態內部類使用程式碼:
1 package com.learnjava.innerclass; 2 3 class StaticInner 4 { 5 private static int a = 4; 6 7 // 靜態內部類8 public static class Inner 9 { 10 public void test() 11 { 12 // 靜態內部類可以訪問外部類的靜態成員 13 // 並且它只能訪問靜態的 14 System.out.println(a); 15 } 16 17 } 18 } 19 20 public class StaticInnerClassTest 21 { 22 23 public static void main(String[] args)24 { 25 StaticInner.Inner inner = new StaticInner.Inner(); 26 inner.test(); 27 } 28 }
成員內部類Member Inner Class
成員內部類也是定義在另一個類中,但是定義時不用static修飾。
成員內部類和靜態內部類可以類比為非靜態的成員變數和靜態的成員變數。
成員內部類就像一個例項變數。
它可以訪問它的外部類的所有成員變數和方法,不管是靜態的還是非靜態的都可以。
在外部類裡面建立成員內部類的例項:
this.new Innerclass();
在外部類之外建立內部類的例項:
(new Outerclass()).new Innerclass();
在內部類裡訪問外部類的成員:
Outerclass.this.member
詳情見程式碼例子:
1 package com.learnjava.innerclass; 2 3 class MemberInner 4 { 5 private int d = 1; 6 private int a = 2; 7 8 // 定義一個成員內部類 9 public class Inner2 10 { 11 private int a = 8; 12 13 public void doSomething() 14 { 15 // 直接訪問外部類物件 16 System.out.println(d); 17 System.out.println(a);// 直接訪問a,則訪問的是內部類裡的a 18 19 // 如何訪問到外部類裡的a呢? 20 System.out.println(MemberInner.this.a); 21 } 22 23 } 24 25 } 26 27 public class MemberInnerClassTest 28 { 29 30 public static void main(String[] args) 31 { 32 33 // 建立成員內部類的物件 34 // 需要先建立外部類的例項 35 MemberInner.Inner2 inner = new MemberInner().new Inner2(); 36 37 inner.doSomething(); 38 } 39 }
區域性內部類Local Inner Class
區域性內部類定義在方法中,比方法的範圍還小。是內部類中最少用到的一種型別。
像區域性變數一樣,不能被public, protected, private和static修飾。
只能訪問方法中定義的final型別的區域性變數。
區域性內部類在方法中定義,所以只能在方法中使用,即只能在方法當中生成區域性內部類的例項並且呼叫其方法。
1 package com.learnjava.innerclass; 2 3 class LocalInner 4 { 5 int a = 1; 6 7 public void doSomething() 8 { 9 int b = 2; 10 final int c = 3; 11 // 定義一個區域性內部類 12 class Inner3 13 { 14 public void test() 15 { 16 System.out.println("Hello World"); 17 System.out.println(a); 18 19 // 不可以訪問非final的區域性變數 20 // error: Cannot refer to a non-final variable b inside an inner 21 // class defined in a different method 22 // System.out.println(b); 23 24 // 可以訪問final變數 25 System.out.println(c); 26 } 27 } 28 29 // 建立區域性內部類的例項並呼叫方法 30 new Inner3().test(); 31 } 32 } 33 34 public class LocalInnerClassTest 35 { 36 public static void main(String[] args) 37 { 38 // 建立外部類物件 39 LocalInner inner = new LocalInner(); 40 // 呼叫外部類的方法 41 inner.doSomething(); 42 } 43 44 }
匿名內部類Anonymous Inner Class
匿名內部類就是沒有名字的區域性內部類,不使用關鍵字class, extends, implements, 沒有構造方法。
匿名內部類隱式地繼承了一個父類或者實現了一個介面。
匿名內部類使用得比較多,通常是作為一個方法引數。
1 package com.learnjava.innerclass; 2 3 import java.util.Date; 4 5 public class AnonymouseInnerClass 6 { 7 8 @SuppressWarnings("deprecation") 9 public String getDate(Date date) 10 { 11 return date.toLocaleString(); 12 13 } 14 15 public static void main(String[] args) 16 { 17 AnonymouseInnerClass test = new AnonymouseInnerClass(); 18 19 // 列印日期: 20 String str = test.getDate(new Date()); 21 System.out.println(str); 22 System.out.println("----------------"); 23 24 // 使用匿名內部類 25 String str2 = test.getDate(new Date() 26 { 27 });// 使用了花括號,但是不填入內容,執行結果和上面的完全一致 28 // 生成了一個繼承了Date類的子類的物件 29 System.out.println(str2); 30 System.out.println("----------------"); 31 32 // 使用匿名內部類,並且重寫父類中的方法 33 String str3 = test.getDate(new Date() 34 { 35 36 // 重寫父類中的方法 37 @Override 38 @Deprecated 39 public String toLocaleString() 40 { 41 return "Hello: " + super.toLocaleString(); 42 } 43 44 }); 45 46 System.out.println(str3); 47 } 48 }
生成的.class檔案中,匿名類會生成OuterClass$1.class檔案,數字根據是第幾個匿名類而類推。
Swing中使用內部類的例子如下:
1 package com.learnjava.innerclass; 2 3 import java.awt.event.ActionEvent; 4 import java.awt.event.ActionListener; 5 import java.awt.event.WindowAdapter; 6 import java.awt.event.WindowEvent; 7 8 import javax.swing.JButton; 9 import javax.swing.JFrame; 10 11 public class SwingTest 12 { 13 public static void main(String[] args) 14 { 15 JFrame frame = new JFrame("JFrame"); 16 JButton button = new JButton("JButton"); 17 18 button.addActionListener(new ActionListener() 19 { 20 // new出來一個實現了ActionListener介面的類的例項 21 22 @Override 23 public void actionPerformed(ActionEvent arg0) 24 { 25 System.out.println("Hello World"); 26 27 } 28 }); 29 30 //加入按鈕 31 frame.getContentPane().add(button); 32 33 //設定關閉行為 34 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 35 36 frame.setSize(200, 200); 37 38 frame.addWindowListener(new WindowAdapter() 39 { 40 //也可以使用繼承了介面卡類的匿名內部類 41 @Override 42 public void windowClosing(WindowEvent e) 43 { 44 45 System.out.println("Closing"); 46 System.exit(0); 47 } 48 }); 49 frame.setVisible(true); 50 } 51 52 }