一、內部類定義
內部類(nested classes),面向對象程序設計中,可以在一個類的內部定義另一個類。嵌套類分為兩種,即靜態嵌套類和非靜態嵌套類。靜態嵌套類使用很少,最重要的是非靜態嵌套類,也即是被稱作為內部類(inner)。內部類是JAVA語言的主要附加部分。內部類幾乎可以處於一個類內部任何位置,可以與實例變量處於同一級,或處於方法之內,甚至是一個表達式的一部分。
為什么需要內部類?
每個內部類都能獨立地繼承自一個(接口的)實現,所以無論外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。如果沒有內部類提供的可以繼承多個具體的或抽象的類的能力,一些設計與編程問題就很難解決。從這個角度看,內部類使得多重繼承的解決方案變得完整。接口解決了部分問題,而內部類有效地實現了“多重繼承”。
二、內部類分類
一、成員內部類
作為外部類的一個成員存在,與外部類的屬性、方法並列。
成員內部類也是定義在另一個類中,但是定義時不用static修飾。
成員內部類和靜態內部類可以類比為非靜態的成員變量和靜態的成員變量。
成員內部類就像一個實例變量。
它可以訪問它的外部類的所有成員變量和方法,不管是靜態的還是非靜態的都可以。
在外部類里面創建成員內部類的實例:
this.new B();
在外部類之外創建內部類的實例:
(new Test1()).new B().go();
在內部類里訪問外部類的成員:
Test1.this.member
1 package memberiner; 2 3 public class Test1 { 4 private String member="這是外部類變量"; 5 //成員內部類 6 //不對外開放,高內聚 7 class B{ 8 public B() {//當內部類的構造器為Protected、private修飾時外部類外不可以訪問 9 10 } 11 public void go(){ 12 System.out.println("這是內部類B的go方法"+Test1.this.member);//內部類訪問外部類變量 13 } 14 } 15 16 17 //可供成員的外部類中其他方法調用 18 public B show(){ 19 20 return this.new B();//外部類調用 21 22 } 23 24 public static void main(String[] args) { 25 26 B b = new Test1().show(); 27 } 28 29 } 30 31 32 package memberiner; 33 34 public class A { 35 36 public static void main(String[] args) { 37 38 new Test1().show(); 39 40 (new Test1()).new B().go();//外部類外訪問內部類 41 } 42 43 }
二、方法內部類(局部內部類)
定義在方法中,比方法的范圍還小。是內部類中最少用到的一種類型。
像局部變量一樣,不能被public, protected, private和static修飾。
只能訪問方法中定義的final類型的局部變量。
方法內部類在方法中定義,所以只能在方法中使用,即只能在方法當中生成方法內部類的實例並且調用其方法
1 package methodinner; 2 3 public class Test { 4 5 class Duanzanshichangzheng { 6 7 public void noProblem() { 8 System.out.println("患有急性短暫失常症,開車撞死人沒事"); 9 10 } 11 12 } 13 14 private String member ="全局變量"; 15 final int n=4; 16 public void driver(){ 17 final String member2 ="局部變量";//方法內的變量只有final變量才能被方法內部類訪問 18 System.out.println("我正在開車"+member); 19 20 //每個內部類都能獨立地繼承自一個(接口的)實現,所以無論外圍類是否已經繼承了某個(接口的)實現, 21 //對於內部類都沒有影響 22 //內部類使得多重繼承的解決方案變得完整。接口解決了部分問題,而內部類有效地實現了“多重繼承” 23 //短暫,不對外,防止變成全局 24 class B extends Duanzanshichangzheng { 25 public void show(){ 26 System.out.println(member2+4); 27 } 28 } 29 new B().noProblem();//方法內部類里的方法只能在方法里調用 30 new B().show(); 31 32 System.out.println("一切恢復正常"); 33 34 } 35 36 public static void main(String[] args) { 37 new Test().driver(); 38 } 39 40 }
三、匿名內部類(Android運用最多)
匿名內部類就是沒有名字的局部內部類,不使用關鍵字class, extends, implements, 沒有構造方法。
什么情況下需要使用匿名內部類?如果滿足下面的一些條件,使用匿名內部類是比較合適的:
a·只用到類的一個實例。
b·類在定義后馬上用到。
c·類非常小(SUN推薦是在4行代碼以下)
d·給類命名並不會導致你的代碼更容易被理解。
在使用匿名內部類時,要記住以下幾個原則:
a·匿名內部類不能有構造方法。
b·匿名內部類不能定義任何靜態成員、方法和類。
c·匿名內部類不能是public,protected,private,static。
d·只能創建匿名內部類的一個實例。
e·一個匿名內部類一定是在new的后面,用其隱含實現一個接口或實現一個類。
f·因匿名內部類為局部內部類,所以局部內部類的所有限制都對其生效。
以下是匿名內部類的實例:
實例背景:輸出每個Doctor博士每天做的事情
1、白天大家都是“白天傳授理論知識”;
2、晚上每個人都是不一樣的
*用以前繼承方法需要寫多個實現類,而匿名內部類只需要實現“晚上做事workInNight()”這個方法就可以了
代碼目錄
1 package anonymousinner; 2 3 public interface Qinshou { 4 public void workInNight(); 5 }
1 package anonymousinner; 2 3 public abstract class Doctor implements Qinshou { 4 //多態,情況不定 5 public void workInDay(){ 6 System.out.println("白天傳授理論知識"); 7 } 8 9 }
1 package anonymousinner; 2 3 public class Doctor1 extends Doctor { 4 5 public void workInNight(){ 6 System.out.println("晚上教彈琴"); 7 } 8 }
1 package anonymousinner; 2 3 public class Doctor2 extends Doctor{ 4 5 public void workInNight(){ 6 System.out.println("晚上學習"); 7 } 8 }
1 package anonymousinner; 2 3 public class Test { 4 5 public static void main(String[] args) { 6 Doctor1 d1 = new Doctor1(); 7 d1.workInDay(); 8 d1.workInNight(); 9 10 Doctor2 d2 = new Doctor2(); 11 d2.workInDay(); 12 d2.workInNight(); 13 14 //語法格式 15 //1、new 抽象類或者接口 16 //2、后加大括號 17 //3、實現未實現方法 18 Doctor d3 = new Doctor(){ 19 20 //匿名內部類 21 public void workInNight() { 22 System.out.println("睡覺"); 23 } 24 25 }; 26 27 d3.workInDay(); 28 d3.workInNight(); 29 } 30 }
匿名內部類細節:
1、
1 //1 2 new Object(){ 3 void show(){ 4 System.out.println("show run"); 5 } 6 }.show();//正確 7 //2 8 Object obj = new Object(){ 9 void show(){ 10 System.out.println("show run"); 11 } 12 }; 13 obj.show();//編譯錯誤
1和2的寫法正確嗎?有區別嗎?說出原因。
寫法是正確,1和2都是在通過匿名內部類建立一個Object類的子類對象。 區別: 第一個可是編譯通過,並運行。 第二個編譯失敗,因為匿名內部類是一個子類對象,當用Object的obj引用指向時,就被提升為了 Object類型,而編譯時檢查Object類中是否有show方法,所以編譯失敗。
2、
1 class InnerClassDemo6 { 2 +(static)class Inner{ 3 void show(){} 4 } 5 public void method(){ 6 this.new Inner().show();//可以 7 } 8 public static void main(String[] args) {//static不允許this 9 This.new Inner().show();//錯誤,Inner類需要定義成static 10 } 11 }
還有很多的不懂,各位大神多多指教喔!