Java之內部類詳解
阿新 • • 發佈:2018-12-26
目錄
內部類
-
概念
在描述事物時,若一個事物內部還包含其他可能包含的事物
-
舉例
比如在描述汽車時,汽車中還包含這發動機,這時發動機就可以使用內部類來描述。汽車和發動機都可以作為完整的類
class 汽車 { //外部類
class 發動機 { //內部類
}
}
-
編譯
內部類編譯完成後也會存在一個class檔案(汽車$發動機.class)
-
內部類分類
成員內部類
位置是定義在外部類中的成員位置,定義格式如下
class 外部類 { 修飾符 class 內部類 { //其他程式碼 } }
訪問方式
外部類名.內部類名 變數名 = new 外部類名().new 內部類名();
呼叫規則:內部類可以使用外部類的成員,而外部類要使用內部類的成員必須要建立物件
案例
1:定義內部類
public class Body { //外部類,身體 private boolean life= true; //生命狀態 public class Heart { //內部類,心臟 public void jump() { System.out.println("心臟噗通噗通的跳"); System.out.println("生命狀態" + life); //訪問外部類成員變數 } } }
2:訪問內部類
public static void main(String[] args) {
//建立內部類物件
Body.Heart bh = new Body().new Heart();
//呼叫內部類中的方法
bh.jump();
}
console:
心臟噗通噗通的跳
生命狀態true
類內部同名變數時呼叫方法:
public class Outer { int i = 1; public class Inner{ int i = 2; public void print(){ int i = 3; System.out.println(i); System.out.println(this.i); System.out.println(Outer.this.i); } } } console: 3 2 1
區域性內部類
位置:定義在外部類方法中的區域性位置
定義格式:
class 外部類 {
修飾符 返回值型別 方法名(引數) {
class 內部類 {
//其他程式碼
}
}
}
訪問方式:
現在內部類中自己呼叫方法(相當於為外部類提供了一個返回值)
在外部類方法中,建立內部類物件,進行訪問
案例:
1:定義內部類
public class Party { //外部類,聚會
public void puffBall(){ // 吹氣球方法
public class Ball { // 內部類,氣球
public void puff(){
System.out.println("氣球膨脹了");
}
}
//建立內部類物件,呼叫puff方法
new Ball().puff();
}
}
2:訪問內部類
public static void main(String[] args) {
//建立外部類物件
Party p = new Party();
//呼叫外部類中的puffBall方法
p.puffBall();
}
console:
氣球膨脹了
匿名內部類
匿名內部類使用區域性變數需要宣告為final
在Java8之前,我們在匿名內部類或者區域性內部類中使用區域性變數都需要將區域性變數宣告為final,這是因為java底層給我們做了一些小動作,匿名內部類表面上沒有建構函式,其實是有的,底層直接將區域性變數通過建構函式傳給內部類,區域性變數在生命週期結束後就會被銷燬,而匿名內部類的生命週期一般來說都比區域性變數長,那麼假如我們可以修改這個變數,就會出現內外不一致的現象(這裡的修改指的是改變引用,而不是改變變數的內容),因為外面的區域性變數是不會因為內部的引用改變而改變的,所以強制要求宣告為final。
作用:匿名內部類是建立某個型別子類物件的快捷方式,格式如下
new 父類或介面(){
//進行方法重寫
}.方法();
原始方式:
//已經存在的父類:
public abstract class Person{
public abstract void eat();
}
//定義並建立該父類的子類物件,並用多型的方式賦值給父類引用變數
Person p = new Person(){
public void eat() {
System.out.println(“我吃了”);
}
};
//呼叫eat方法
p.eat();
快捷方式(借用匿名類):
//方式一(只能呼叫一個重構方法)
new Person(){
public void eat() {
System.out.println(“我吃了”);
}
}.eat();
//方式二(可以呼叫多個重構方法,原理:多型,父類引用指向子類物件)
Person p = new Person(){
public void eat() {
System.out.println(“我吃了”);
}
//可能存在其他抽象方法
}
p.eat();
//可以繼續使用p.方法名()去呼叫其他實現的抽象方法