(一)
内部類概述
把類定義在另一個類的内部,該類就被稱為内部類。
舉例:把類Inner定義在類Outer中,類Inner就被稱為内部類。
class Outer {
class Inner {
}
}
複制

(二)
内部類的通路規則
A:可以直接通路外部類的成員,包括私有
B:外部類要想通路内部類成員,必須建立對象

(三)
内部類的分類
A:成員内部類
B:局部内部類
C:靜态内部類
D:匿名内部類
(1) 成員内部類
成員内部類——就是位于外部類成員位置的類
特點:可以使用外部類中所有的成員變量和成員方法(包括private的)
A:格式:
class Outer {
private int age = 20;
//成員位置
class Inner {
public void show() {
System.out.println(age);
}
}
}
class Test {
public static void main(String[] ages) {
//成員内部類是非靜态的示範
Outer.Inner oi = new Outer.new Inner();
oi.show();
}
}
複制
B:建立對象時:
//成員内部類不是靜态的:
外部類名.内部類名 對象名 = new 外部類名.new 内部類名();
//成員内部類是靜态的:
外部類名.内部類名 對象名 = new 外部類名.内部類名();
複制
C:成員内部類常見修飾符:
A:private
如果我們的内部類不想輕易被任何人通路,可以選擇使用private修飾内部類,這樣我們就無法通過建立對象的方法來通路,想要通路隻需要在外部類中定義一個public修飾的方法,間接調用。這樣做的好處就是,我們可以在這個public方法中增加一些判斷語句,起到資料安全的作用。
class Outer {
private class Inner {
public void show() {
System.out.println(“密碼備份檔案”);
}
}
public void method() {
if(你是管理者){
Inner i = new Inner();
i.show();
}else {
System.out.println(“你沒有權限通路”);
}
}
}
複制
下面我們給出一個更加規範的寫法
class Outer {
private class Inner {
public void show() {
System.out.println(“密碼備份檔案”);
}
}
//使用getXxx()擷取成員内部類,可以增加校驗語句(文中省略)
public void getInner() {
return new Inner();
}
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.getInner();
inner.show();
}
}
複制
B:static
這種被 static 所修飾的内部類,按位置分,屬于成員内部類,但也可以稱作靜态内部類,也常叫做嵌套内部類。具體内容我們在下面詳細講解。
D:成員内部類經典題(填空)
請在三個println 後括号中填空使得輸出25,20,18
class Outer {
public int age = 18;
class Inner {
public int age = 20;
public viod showAge() {
int age = 25;
System.out.println(age);//空1
System.out.println(this.age);//空2
System.out.println(Outer.this.age);//空3
}
}
}
複制
(2) 局部内部類
局部内部類——就是定義在一個方法或者一個作用域裡面的類
特點:主要是作用域發生了變化,隻能在自身所在方法和屬性中被使用
A 格式:
class Outer {
public void method(){
class Inner {
}
}
}
複制
B:通路時:
//在局部位置,可以建立内部類對象,通過對象調用和内部類方法
class Outer {
private int age = 20;
public void method() {
final int age2 = 30;
class Inner {
public void show() {
System.out.println(age);
//從内部類中通路方法内變量age2,需要将變量聲明為最終類型。
System.out.println(age2);
}
}
Inner i = new Inner();
i.show();
}
}
複制
C: 為什麼局部内部類通路局部變量必須加final修飾呢?
因為局部變量是随着方法的調用而調用,使用完畢就消失,而堆記憶體的資料并不會立即消失。
是以,堆記憶體還是用該變量,而該變量已經沒有了。為了讓該值還存在,就加final修飾。
原因是,當我們使用final修飾變量後,堆記憶體直接存儲的是值,而不是變量名。
(即上例 age2 的位置存儲着常量30 而不是 age2 這個變量名)
(3) 靜态内部類
我們所知道static是不能用來修飾類的,但是成員内部類可以看做外部類中的一個成員,是以可以用static修飾,這種用static修飾的内部類我們稱作靜态内部類,也稱作嵌套内部類.
特點:不能使用外部類的非static成員變量和成員方法
解釋:非靜态内部類編譯後會預設的儲存一個指向外部類的引用,而靜态類卻沒有。
簡單了解:
即使沒有外部類對象,也可以建立靜态内部類對象,而外部類的非static成員必須依賴于對象的調用,靜态成員則可以直接使用類調用,不必依賴于外部類的對象,是以靜态内部類隻能通路靜态的外部屬性和方法。
class Outter {
int age = 10;
static age2 = 20;
public Outter() {
}
static class Inner {
public method() {
System.out.println(age);//錯誤
System.out.println(age2);//正确
}
}
}
public class Test {
public static void main(String[] args) {
Outter.Inner inner = new Outter.Inner();
inner.method();
}
}
複制
(4) 匿名内部類
一個沒有名字的類,是内部類的簡化寫法
A 格式:
new 類名或者接口名() {
重寫方法();
}
複制
本質:其實是繼承該類或者實作接口的子類匿名對象
這也就是下例中,可以直接使用 new Inner() {}.show(); 的原因 == 子類對象.show();
interface Inter {
public abstract void show();
}
class Outer {
public void method(){
new Inner() {
public void show() {
System.out.println("HelloWorld");
}
}.show();
}
}
class Test {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
複制
如果匿名内部類中有多個方法又該如何調用呢?
Inter i = new Inner() { //多态,因為new Inner(){}代表的是接口的子類對象
public void show() {
System.out.println("HelloWorld");
}
};
複制
B:匿名内部類在開發中的使用
我們在開發的時候,會看到抽象類,或者接口作為參數。
而這個時候,實際需要的是一個子類對象。
如果該方法僅僅調用一次,我們就可以使用匿名内部類的格式簡化。