本文主要介紹內部類(inner class)的一些基本應用,將從內部類的分類角度,首先對每個具體內部類進行介紹。主要包括普通的內部類【common inner class】、局部內部類[local inner class]、嵌套內部類【nested innner class】、匿名內部類【anonymous inner class】、而後比較一下局部內部類[local inner class]和匿名內部類【anonymous inner class ]的區別,進而知道在具體狀況下該選擇內部類,即到底用local inner class仍是anonymous inner class。最後介紹內部類的應用。java
一:首先對每個具體內部類進行介紹ide
1.普通的內部類【common inner class】函數
定義:在一個類裏面直接定義一個類:this
一些詳細狀況看代碼:spa
1 package com.qls.comonInnerClass; 2 3 public class A { 4 /** 5 * 從B C D E 這四個普通內部類中能夠看出類前面的修飾符能夠是 6 * private protected default(也就是什麼修飾符沒有的D) public. 而在局部內部類中修飾類的只能是: 7 * abstract 或final 或者什麼修飾符都沒有。 8 * 注意的問題以下: 9 * 1.一般狀況下:外部類會有一個返回內部類引用的一個方法如getB()這個方法。 10 * 2.如何在內部類中用this指代外部類引用?【答:外部類名.this 參考第19行代碼。】 11 * 以及如何建立內部類的一個實例?【答:x.new B() 其中x是外部類的一個實例,B爲一個內部類。 12 * 如果直接寫new B()會報錯。參考第3八、39兩行代碼。】 13 * 上述兩個注意點對其餘的內部類也適用。 14 * @author 秦林森 15 * 16 */ 17 private class B { 18 public A outer(){ 19 return A.this;//A.this是指代A的一個引用。 20 } 21 } 22 protected class C{ 23 24 } 25 class D{ 26 27 } 28 public class E{ 29 30 } 31 /** 32 * 返回內部類的引用: 33 */ 34 B getB(){ 35 return new B(); 36 } 37 public static void main(String[] args) { 38 A a = new A(); 39 B b = a.new B(); 40 } 41 }
局部內部類【local innner class】code
定義:把類定義在方法裏面,或者是方法中的某一個區域中。對象
代碼以下:blog
1 package com.qls.localInnerClass2; 2 /** 3 * 定義:the creation of an entire class within the scope of a method,or Nesting a class within 4 * a scope of a method. 5 * This is called a local inner class. 6 * 注意狀況以下: 7 * 1.局部內部類【local inner class】若是想要修飾的話,只有abstract 和final能夠, 8 * 其他的如(public protected)等都不能夠。 9 * 2.在局部內部類中只能訪問包含該內部類的範圍(enclosing scope)的final變量。若不是則會報錯。 10 * 11 * @author 秦林森 12 * 13 */ 14 public class A { 15 public void ouyangfeng(){ 16 //把類D定義在方法ouyangfeng()的某個區域中。 17 if(3>2){ 18 class D{ 19 20 } 21 } 22 final class B{ 23 24 } 25 } 26 27 public void sixi(final String s){ 28 int e=1; 29 final int c=8; 30 class C{ 31 /** 32 * 在局部內部類或者匿名內部類中只能訪問包含該內部類的範圍(enclosing scope)的final變量。 33 * 若不是則會報錯。 34 * 如int f=e;編譯器報錯。 35 */ 36 String str=s; 37 int d=c; 38 // int f=e;//編譯器報錯。 39 } 40 } 41 public static void main(String[] args) { 42 // TODO Auto-generated method stub 43 44 } 45 46 }
匿名內部類:沒有名字的內部類。繼承
下面的代碼介紹瞭如下的內容:接口
1.匿名內部類實現一個接口,
2.匿名內部類實現一個沒有默認構造方法的抽象類
3.匿名內部類和局部內部類同樣把參數定義成final,完成字段初始化
4.匿名內部類用普通代碼塊{}完成初始化,彌補了匿名內部類沒有構造方法的缺陷。
代碼以下:
package com.qls.anonymouseInnerClass; /** * 匿名內部類(anonymous inner class)通常用在return 語句中。 * 注意狀況以下: * 匿名內部類因爲沒有名字,天然而然也就沒有構造方法,其餘三種內部類都有構造方法。 * 沒有構造方法怎麼給對象賦值進行初始化呢?【答:用普通的代碼塊{},在這個代碼塊裏面實行初始化。】 * @author 秦林森 * */ interface B{ void ouyangfeng(); } abstract class C{ private int i; public C(int i) { this.i=i; } public abstract int value(); } public class A { public B getB(){ //new B(){};就是匿名內部類:用默認的構造方法 return new B() { @Override public void ouyangfeng() { // TODO Auto-generated method stub System.out.println("ouyangfeng is chief village of sixi "); } }; } public C getC(final int i){ //匿名內部類用一個帶參數的構造方法 return new C(i) { //用普通代碼塊實現初始化: { //這裏寫兩個輸出語句做爲演示。 System.out.println("泗溪"); System.out.println("ouyangfeng"); System.out.println(value());//輸出value的值 } @Override public int value() { // TODO Auto-generated method stub return i;//從這裏能夠看出要想引用i,必須把i定義成final。這和局部內部類同樣。 } }; } public static void main(String[] args) { // TODO Auto-generated method stub new A().getC(4);//輸出泗溪、ouyangfeng、4 } }
嵌套內部類:
1 package com.qls.nestedClass; 2 /** 3 * 若是你不想讓內部類的對象和外部類的對象有如何聯繫的話,你就能夠把內部類定義成static 4 * 嵌套內部類(Nested inner class)的定義:類中關鍵詞static修飾的內部類。 5 * 注意狀況以下: 6 * 1.在嵌套內部類中不能訪問外部類的非靜態變量。 7 * 2.建立內部類變量時,你不想經過建立外部類變量才能建立內部類變量時,你能夠把這個內部類定義成static 8 * 即嵌套內部類。 9 * 3.在接口interface中定義的內部類默認都是public static 的,因此在接口中的內部類必是嵌套內部類。 10 * @author 秦林森 11 * 12 */ 13 interface D{ 14 void hello(); 15 class Test implements D{ 16 17 @Override 18 public void hello() { 19 // TODO Auto-generated method stub 20 System.out.println("hello"); 21 } 22 public static void main(String[] args) { 23 /** 24 * 因爲Test類默認是public static 的,因此建立Test對象時,不須要經過外部類D, 25 * 因此直接new Test()便可建立Test類中的一個對象。 26 * 話又說回來了,若是在接口中的類不是public static 的那麼這個內部類也就是普通的內部類 27 * 在建立Test的對象時,也就須要外部類的對象。關鍵D是接口,你怎麼new 呢? 28 * 因此在的類只能是static 的。 29 */ 30 new Test().hello();//輸出hello 31 } 32 } 33 } 34 public class A { 35 int a=9; 36 public static class B{ 37 // int b=a;編譯報錯 38 void f(){ 39 System.out.println("f()"); 40 } 41 } 42 public static void main(String[] args) { 43 /** 44 * 從這裏你看到了,能夠對B直接new ,訪問B中的函數f(). 45 * 可是若是B沒有static這個關鍵字,即B是普通內部類時,必須這樣才能訪問到f() 46 * new A().new B().f(); 47 */ 48 new B().f(); 49 } 50 }
二:比較一下局部內部類[local inner class]和匿名內部類【anonymous inner class ]的區別
1.匿名內部類沒有構造犯法,二局部內部類有構造方法。
2.若是在一個外部類有兩個或兩個以上的方法,返回的都是某個接口或者抽象類的引用,建議把寫一個局部內部類。若寫成匿名內部類時,代碼會顯得特別冗長。反之若是一個時,建議用匿名內部類。
代碼以下:
1 package com.qls.anonymouseInnerClass; 2 interface Six{ 3 void six(); 4 } 5 public class Ouyangfeng { 6 private class SixTest implements Six{ 7 8 @Override 9 public void six() { 10 // TODO Auto-generated method stub 11 12 } 13 14 } 15 public Six f(){ 16 return new SixTest(); 17 } 18 public Six g(){ 19 return new SixTest(); 20 } 21 }
三:內部類的應用:
用內部類實現java的多重繼承。
1 package com.qls.anonymouseInnerClass; 2 class D{ 3 4 } 5 abstract class E{ 6 7 } 8 class F extends D{ 9 //這是實現多重繼承的核心代碼。這裏是用一個匿名內部類實現 10 E makeE(){ 11 return new E() { 12 }; 13 } 14 } 15 public class MultipleInherit { 16 public static void takesD(D d){ 17 18 } 19 public static void takesE(E d){ 20 21 } 22 public static void main(String[] args) { 23 // TODO Auto-generated method stub 24 F d = new F(); 25 takesD(d); 26 takesE(d.makeE()); 27 } 28 29 }
最後簡要介紹一下讓一個類繼承另外一個類中的內部類?以及怎麼讓一個類中的內部類繼承另外一個類的內部類呢?
首先是:讓一個類繼承另外一個類中的內部類
代碼以下:
1 package com.qls.anonymouseInnerClass; 2 3 import com.qls.anonymouseInnerClass.WithInner.Inner; 4 5 class WithInner{ 6 class Inner{ 7 private int a; 8 public Inner(int a) { 9 this.a=a; 10 } 11 public Inner() { 12 // TODO Auto-generated constructor stub 13 } 14 } 15 } 16 public class InheritInner extends Inner{ 17 public InheritInner(WithInner withInner) { 18 // TODO Auto-generated constructor stub 19 /** 20 * 這句話必需要寫。不然編譯器會報錯。即:外部類的一個對象.super(). 21 * 這裏的super(),比奧斯Inner的一個默認構造方法。 22 * 若是Inner中好比有這樣一個構造方法:public Inner(int a) 23 * 你如今也能夠寫成:把withInner.super();改成withInner.super(1);編譯器是不會報錯的。 24 * 若是沒有默認構造方法public Inner() 則這題必須寫成:withInner.super(1);的形式。 25 */ 26 27 withInner.super(); 28 } 29 public static void main(String[] args) { 30 // TODO Auto-generated method stub 31 WithInner withInner = new WithInner(); 32 InheritInner inheritInner = new InheritInner(withInner); 33 } 34 35 }
讓一個類中的內部類繼承另外一個類的內部類
代碼以下:
1 package com.qls.anonymouseInnerClass; 2 /** 3 * 朱元璋家住鳳陽,劉伯溫家住青田 4 * @author 秦林森 5 * 6 */ 7 class ZhuYuanZhang{ 8 class FengYang{ 9 private String location; 10 11 public FengYang(String location) { 12 this.location = location; 13 } 14 15 } 16 } 17 class LiuBoWei{ 18 class QingTian extends ZhuYuanZhang.FengYang{ 19 private String location; 20 public QingTian(ZhuYuanZhang zhuYuanZhang, String location) { 21 zhuYuanZhang.super(location);//這句話必需要寫。或者會報錯, 22 this.location=location; 23 } 24 public void accurate(){ 25 System.out.println("一統江山劉伯溫 ,家在"+location); 26 } 27 } 28 } 29 public class Test { 30 31 public static void main(String[] args) { 32 // TODO Auto-generated method stub 33 new LiuBoWei().new QingTian(new ZhuYuanZhang(), "青田").accurate(); 34 } 35 36 }/*Output: 37 一統江山劉伯溫 ,家在青田*///:~