一、什么是內部類?
到底什么是內部類呢?通俗的講,就是在類內部定義的類,包括定義在一個類的方法外面、方法里面或者代碼塊中。
二、為什么要使用內部類?
為什么我們要不走尋常路,把一個類定義在另一個類的內部呢?這樣到底是出于什么目的呢?其實內部類是為了彌補java的單繼承的特點,以實現多繼承。內部類可以繼承抽象類或實現接口。這樣外部類也繼承一個父類,就變相的實現了多繼承。內部類可以訪問外部類的屬性,包括私有屬性。
三、成員內部類
先上代碼:
package noStaticInnerClass;public class OuterClass { PRivate int outerPrivateParam = 1; public int outerPublicParam = 2; public static int outerStaticParam = 3; void outerFun() { System.out.println("function in outer class."); } public class InnerClass { public int innerParam = 4; //在非靜態內部類中不可以定義靜態變量,以下會報編譯錯 //public static innerStaticParam = 5; public void innerFun() { System.out.println("outerPrivateParam : " + outerPrivateParam + ", outerPublicParam : " + outerPublicParam + ", outerStaticParam : " + outerStaticParam); //訪問外部類的方法 outerFun(); } } public void test() { InnerClass inner = new InnerClass(); inner.innerFun(); } public static void main(String[] args) { OuterClass outer = new OuterClass(); outer.test(); }}成員內部類是一種個Field、方法、構造器和初始化塊相似的類成員?! 〕蓡T內部類又被稱為非靜態內部類,它具有以下幾個特性:
package noStaticInnerClass;public class OuterClass { private int outerPrivateParam = 1; public int outerPublicParam = 2; public static int outerStaticParam = 3; public class InnerClass { public int innerParam = 4; //在非靜態內部類中不可以定義靜態變量,以下會報編譯錯 //public static innerStaticParam = 5; public void innerFun() { System.out.println("outerPrivateParam : " + outerPrivateParam + ", outerPublicParam : " + outerPublicParam + ", outerStaticParam : " + outerStaticParam); } } public static void test() { //不可以在外部類的靜態方法中直接創建內部類對象 //InnerClass inner = new InnerClass(); OuterClass out = new OuterClass(); InnerClass inner = out.new InnerClass(); inner.innerFun(); }}這是因為靜態方法是類相關的,test方法不需要創建外部類的實例,就可以通過OuterClass.test()來調用,但是非靜態內部類對象是依賴外部類的實例對象才能創建的,所以要先顯式創建外部類對象。
非靜態內部類的上一級是外部類,所以非靜態內部類可以用private、protected、public以及默認修飾符來修飾內部類。如何在外部類以外的部分創建內部類對象呢?
外部類 外部類實例名 = new 外部類();
外部類.內部類 內部類實例名 = 外部類實例名.new 內部類();
四、靜態內部類
繼續看代碼:
package noStaticInnerClass;public class OuterClass { private int outerPrivateParam = 1; public int outerPublicParam = 2; public static int outerStaticParam = 3; void outerFun() { //外部類可以通過內部類.靜態成員來訪問內部類的靜態成員 System.out.println(InnerClass.innerStaticParam); } static void outerStaticFun() { InnerClass.innerStaticFun(); } public static class InnerClass { public static int innerStaticParam = 5; public int innerParam = 4; public void innerFun() { //在靜態內部類中不能訪問外部類的非靜態成員,以下會報編譯錯。 //System.out.println("outerPrivateParam : " + outerPrivateParam); //ouerFun(); System.out.println("outerStaticParam : " + outerStaticParam); outerStaticFun(); } public static void innerStaticFun() { System.out.println(innerStaticParam); } } public void test() { InnerClass inner = new InnerClass(); System.out.println(inner.innerParam); } public static void main(String[] args) { OuterClass.InnerClass inner = new OuterClass.InnerClass(); inner.innerFun(); OuterClass.InnerClass.innerStaticFun(); }}五、局部內部類
局部內部類放在方法中定義,局部內部類僅在方法內有效。局部類不能使用訪問控制修飾符和static修飾符來修飾。
若需要用局部內部類來創建實例或派生子類,那么只能在局部內部類所在的方法或代碼塊內進行。
package noStaticInnerClass;public class OuterClass { private int outerPrivateParam = 1; public int outerPublicParam = 2; public static int outerStaticParam = 3; void outerFun() { class InnerClass { public int innerParam = 4; public void innerFun() { System.out.println("outerPrivateParam : " + outerPrivateParam + ", outerPublicParam : " + outerPublicParam + ",outerStaticParam : " + outerStaticParam); } } InnerClass inner = new InnerClass(); inner.innerFun(); System.out.println(inner.innerParam); } public static void main(String[] args) { OuterClass out = new OuterClass(); out.outerFun(); }}我們查看以上代碼生成的class文件,發現內部類的class文件名中多了一個1,那是因為同一個類中可能有兩個以上同名的局部內部類。它們在不同的方法中定義。
六、匿名內部類
適合創建只需要一次使用的類。
格式 :
new 父類構造器(實參列表) | 實現接口()
{
//匿名內部類的類體部分。
}
代碼如下 :
package innerClass;public class OutterClass { public TestInterface getInnerClass() { return new TestInterface() { @Override public void print(String name) { System.out.println(name); }; }; } public static void main(String[] args) { OutterClass out = new OutterClass(); out.getInnerClass().print("demo"); }}創建匿名內部類時會立即創建一個類的實例,這個類定義會立即消失。
匿名內部類必須繼承一個父類,或實現一個接口。
注意 :
package innerClass;public class OutterClass { public TestInterface getInnerClass(final String sex) { final int age = 23; return new TestInterface() { @Override public void print(String name) { System.out.println(name + " is a " + sex + " and age is " + age); }; }; } public static void main(String[] args) { OutterClass out = new OutterClass(); out.getInnerClass("boy").print("demo"); }}如果匿名內部類要訪問外部類的局部變量,則必須使用final修飾符來修飾外部類的局部變量。否則編譯部通過。
因為這里是拷貝引用,為了避免引用值發生改變,例如被外部類的方法修改等,而導致內部類得到的值不一致,于是用final來讓該引用不可改變。
新聞熱點
疑難解答