Java基礎 -- 內部類
阿新 • • 發佈:2020-09-17
1、內部類
內部類是定義在一個類的內部的類,內部類 不能定義靜態變數和方法。介面內也可以使用內部類,但沒必要
- 更好的實現隱藏:內部類可以被 private 與 protected 修飾
- 內部類擁有外部類的所有元素的訪問許可權:可以直接呼叫所有外部類的成員,包括 private 修飾的變數和方法、非靜態變數和方法等
- 可以間接的實現多重繼承:一個類中可以寫多個內部類,分別繼承不同的類
- 可以避免實現的介面或繼承的類中有同名的方法
- 當想要定義一個回撥函式且不想編寫大量程式碼時,使用匿名內部類比較便捷
1.1 內部類區別
1.2 成員內部類
public class Test { public int x = 1; private static int y = 10; String str = "Test"; public void m1() { System.out.println("Test m1"); } private static void m2() { System.out.println("Test m2"); } void str() { System.out.println("Test str"); } // 成員內部類 class InnerClass { String str = "InnerClass"; void method() { // 外部類成員變數 System.out.println(x); // 外部類靜態變數 System.out.println(y); // 同名變數,優先呼叫內部類變數 System.out.println(str); // 外部類同名變數 System.out.println(Test.this.str); // 外部類方法 m1(); // 外部類靜態方法 m2(); // 同名方法,優先呼叫內部類方法 str(); // 外部類同名方法 Test.this.str(); } void str() { System.out.println("InnerClass str"); } } public static void main(String[] args) { // 先建立外部類物件 Test test = new Test(); // 通過外部類物件建立內部類物件 Test.InnerClass inner = test.new InnerClass(); // 呼叫內部類方法 inner.method(); // 呼叫內部類成員變數 System.out.println(inner.str); } }
1.3 靜態內部類
被 static 修飾的成員內部類,不需要依賴於外部類的,可以看做靜態變數,不能直接使用外部類的非靜態變數或方法
public class Test { public int x = 1; private static int y = 10; String str = "Test"; public void m1() { System.out.println("Test m1"); } private static void m2() { System.out.println("Test m2"); } void str() { System.out.println("Test str"); } static class InnerClass { private String str = "InnerClass"; static int i = 10; void method() { // 外部類成員變數 System.out.println(new Test().x); // 外部類靜態變數 System.out.println(y); // 同名變數,優先呼叫內部類變數 System.out.println(str); // 外部類同名變數 System.out.println(new Test().str); // 外部類方法 new Test().m1(); // 外部類靜態方法 m2(); // 同名方法,優先呼叫內部類方法 str(); // 外部類同名方法 new Test().str(); } static void staticMethod() { // 同名變數,優先呼叫內部類變數 System.out.println(new InnerClass().str); // 外部類同名變數 System.out.println(new Test().str); // 同名方法,優先呼叫內部類方法 new InnerClass().str(); // 外部類同名方法 new Test().str(); } void str() { System.out.println("InnerClass str"); } } public static void main(String[] args) { // 與成員內部類相比,無需建立外部類物件 InnerClass inner = new InnerClass(); // 呼叫內部類方法 inner.method(); // 呼叫內部類靜態方法 InnerClass.staticMethod(); // 呼叫內部類成員變數 System.out.println(inner.str); // 呼叫內部類靜態成員變數 System.out.println(InnerClass.i); } }
1.4 區域性內部類
public class Test { public int x = 1; private static int y = 10; String str = "Test"; public void m1() { System.out.println("Test m1"); } private static void m2() { System.out.println("Test m2"); } void str() { System.out.println("Test str"); } public static void main(String[] args) { class InnerClass { private String str = "InnerClass"; void method() { // 外部類成員變數 System.out.println(new Test().x); // 外部類靜態變數 System.out.println(y); // 同名變數,優先呼叫內部類變數 System.out.println(str); // 外部類同名變數 System.out.println(new Test().str); // 外部類方法 new Test().m1(); // 外部類靜態方法 m2(); // 同名方法,優先呼叫內部類方法 str(); // 外部類同名方法 new Test().str(); } void str() { System.out.println("InnerClass str"); } } // 建立內部類物件 InnerClass inner = new InnerClass(); // 呼叫內部類方法 inner.method(); // 呼叫內部類成員變數 System.out.println(inner.str); } }
1.5 匿名內部類
沒有名稱的類,利用父類的建構函式和自身類體構造成一個類,其他地方不能引用,沒有構造器,不能例項化,只能使用一次
public class Test {
int i = 10;
One o1 = new One() {
int i = 1;
@Override
void show() {
System.out.println("o1 show");
}
};
void say() {
System.out.println("Test say");
}
public static void main(String[] args) {
One o2 = new One() {
@Override
void show() {
System.out.println("o2 show");
}
void say() {
System.out.println("o2 say");
}
};
// 定義在方法體外,則需要建立外部類物件
Test test = new Test();
// 呼叫內部類方法,o1重寫後的方法
test.o1.show(); // o1 show
// 呼叫內部類成員變數
System.out.println(test.o1.i); // 0
// 定義在方法體內,可以直接使用
o2.show(); // o2 show
// 只能呼叫One中包含的方法及變數
o2.say(); // 編譯錯誤
}
}
class One {
int i = 0;
void show() {
System.out.println("one show");
}
}
1.6 小夥汁,你見過內部內部內部內部內部內部類嗎
public class Test {
class InnerClass {
class InnerInnerClass {
class InnerInnerInnerClass {
class InnerInnerInnerInnerClass {
class InnerInnerInnerInnerInnerClass {
class InnerInnerInnerInnerInnerInnerClass {
void show() {
System.out.println("內部內部內部內部內部內部類");
}
}
}
}
}
}
}
public static void main(String[] args) {
Test test = new Test();
Test.InnerClass.InnerInnerClass.InnerInnerInnerClass.InnerInnerInnerInnerClass.InnerInnerInnerInnerInnerClass.InnerInnerInnerInnerInnerInnerClass inner = test.new InnerClass().new InnerInnerClass().new InnerInnerInnerClass().new InnerInnerInnerInnerClass().new InnerInnerInnerInnerInnerClass().new InnerInnerInnerInnerInnerInnerClass();
inner.show();
}
}