什麼是內部類
將一個類A定義在另一個類B裏面,裏面的那個類A就稱爲內部類,B則稱爲外部類。在描述事物時,若一個事物內部還包含其他事物,就可以使用內部類這種結構。比如,汽車類 Car 中包含發動機類 Engine。內部類仍然是一個獨立的類,在編譯之後會內部類會被編譯成獨立的.class文件,但是前面冠以外部類的類名 和$符號 。 比如,Person$Heart.class
內部類分類
- 成員內部類
- 局部內部類
成員內部類
- 成員內部類 :定義在類中方法外的類
定義格式:
修飾符 class 外部類名稱 {
修飾符 class 內部類名稱 {
// ...
}
// ...
}
注意:
- 如果是內部類,想要訪問外部類的屬性和方法,可以隨意訪問
如何使用成員內部類?
- 間接方式:在外部類的方法當中,使用內部類;然後main只是調用外部類的方法。
- 直接方式,公式:外部類名稱.內部類名稱 對象名 = new 外部類名稱().new 內部類名稱();
例如:
定義內部類
public class Body {//外部類
//外部類成員變量
private String name;
public class Heart {//內部類
public void innerMethod() {
System.out.println("我是內部類的方法");
//訪問外部類的成員變量
System.out.println("我的name是" + name);
}
}
//外部類方法
public void outsideMethod() {
System.out.println("我是外部類方法");
//在外部類的方法當中,使用內部類
new Heart().innerMethod();
}
//外部類get/set方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
定義測試類
public class BodyTest {
public static void main(String[] args) {
// 通過外部類的對象,調用外部類的方法,裏面間接在使用內部類Heart
new Body().outsideMethod();
System.out.println("=====================");
Body.Heart heart = new Body().new Heart();
//調用內部類方法
heart.innerMethod();
}
}
代碼執行後的結果
內部類的同名變量的訪問問題
如果出現了外部類和內部類重名現象,那麼在內部類中訪問外部類的成員變量格式:外部類名稱.this.外部類成員變量名
例如
public class Outer {
int num = 10; // 外部類的成員變量
public class Inner /*extends Object*/ {
int num = 20; // 內部類的成員變量
public void methodInner() {
int num = 30; // 內部類方法的局部變量
System.out.println(num); // 局部變量,就近原則
System.out.println(this.num); // 內部類的成員變量
System.out.println(Outer.this.num); // 外部類的成員變量
}
}
}
局部內部類
如果一個類是定義在一個方法內部的,那麼這就是一個局部內部類。“局部”:只有當前所屬的方法才能使用它,出了這個方法外面就不能用了。
定義格式:
修飾符 class 外部類名稱 {
修飾符 返回值類型 外部類方法名稱(參數列表) {
class 局部內部類名稱 {
// ...
}
}
}
注意事項:
定義一個類的時候,權限修飾符規則:
- 外部類:public / (default)
- 成員內部類:public / protected / (default) / private
- 局部內部類:什麼都不能寫
例如
class MyOuter {
public void methodOuter() {
class Inner { // 局部內部類
int num = 10;
public void methodInner() {
System.out.println(num);
}
}
//創建局部內部類對象
Inner inner = new Inner();
//使用內部類方法
inner.methodInner();
}
}
局部內部類的final問題
局部內部類,如果希望訪問所在方法的局部變量,那麼這個局部變量必須是【有效final的】。備註:從Java 8+開始,只要局部變量事實不變,那麼final關鍵字可以省略。
原因:
- new出來的對象在堆內存當中。
- 局部變量是跟着方法走的,在棧內存當中。
- 方法運行結束之後,立刻出棧,局部變量就會立刻消失。
- 但是new出來的對象會在堆當中持續存在,直到垃圾回收消失。