內部類,靜態內部類,匿名內部類這三種類,從名稱上來說,他們的共同點就是內部類,即顧名思義爲在一個類(以A表示)中定義另外一個類(以B表示),那麼B類就叫內部類,A類就叫外部類
內部類
內部類,也稱嵌套類,顧名思義就是在一個A類裏面嵌套另外一個普通的B類
public class ClazzOuter {
//外部類A
class ClazzInter {//
//內部類B
}
}
- 內部類擁有外部類的所有元素的訪問權
public class ClazzOuter {
private String outerData1 = "這是外部類 private 變量";
public String outerData2 = "這是外部類 public 變量";
private String getOuterData() {
return outerData1 + "|" + outerData2;
}
class ClazzInter {
private String interData1 = "這是內部類 private 變量";
public String interData2 = "這是內部類 public 變量";
public ClazzInter() {
System.out.println("interData1:" + interData1 + ",interData2:" + interData1);
String outerData = getOuterData();
interData1 = outerData1;
interData2 = outerData2;
System.out.println("interData1:" + interData1 + ",interData2:" + interData1 + ",outerData:" + outerData);
}
}
public static void main(String[] args) {
//實例化內部類
new ClazzOuter().new ClazzInter();
}
}
輸出內容
interData1:這是內部類 private 變量,interData2:這是內部類 private 變量
interData1:這是外部類 private 變量,interData2:這是外部類 private 變量,outerData:這是外部類 private 變量|這是外部類 public 變量
從輸出內容,我們可以得出:B類可以直接訪問A類中的元素
其中元素包括成員變量、常量、以及方法,甚至對象等,而這些元素,同時還可以是各種作用域下的元素(全文中的元素同指這些內容
)
2. A類要訪問B類時,必須使用B類的引用
public class ClazzOuter {
//...
class ClazzInter {
//...
public ClazzInter() {
//...
}
public String getInterData1() {
return interData1;
}
}
public static void main(String[] args) {
//實例化內部類
ClazzInter inter = new ClazzOuter().new ClazzInter();
inter.getInterData1();
}
}
以上可以驗證在A類中如果需要使用B類,那麼就需要對B類進行實例,然後使用B類的對象引用進行訪問B類的成員,其中的原因,如果有閱讀過《Java編程思想》中的this關鍵字
說明,就會明白:其實inter.getInterData1();
這句的調用在編譯器中的內部形態是ClazzInter.getInterData1(inter);
也就是說編譯器會把所操作對象的引用
作爲第一個參數傳給getInterData1()
方法
3. 內部類的成員不能被static進行修飾
上述異常包括兩點內容:
- 內部類中不能有static修飾的成員
- 被static修飾的成員不能直接使用非static修飾的成員
靜態內部類
靜態內部類,其實就是在
內部類
的基礎上,多了個static修飾符
public class ClazzOuter {
//外部類A
static class ClazzInter {//
//內部類B
}
}
對比內部類,
- 在B類中只能訪問A類中被static進行修飾的元素
- 可在B類中可以定義靜態元素和非靜態元素
- A類可以直接訪問B類中被static進行修飾的元素:
A.B.static修飾的元素
,A類對B類中未被static修飾的元素,依然需要使用內部類中A類對B類的訪問方式
匿名內部類
匿名內部類,就是一個沒有顯式的名字的內部類,它的本質就是隱式的繼承一個類或者實現一個接口,或者說,匿名內部類是一個繼承了該類或者實現了該接口的子類匿名對象
以接口爲例,接口本身是不能被New出來的,但是在如果要強行使用New的方式來實例它,我們會發現這個接口會帶一對{}
,並且需要實現該接口中定義的內容,那麼New出來的這個對象其實是這個接口的實現類,所以它並沒有類的名字
public class ClazzOuter {
//待實現的接口,在匿名內部類的定義中,這個接口也可以改爲抽象類
interface IClazzInner {
String onTest2Inner();
}
public static void main(String[] args) {
//實現接口的方式的匿名內部類方式一
class ClazzInner implements IClazzInner {
@Override
public String onTest2Inner() {
return "這是一個實現了IClazzInner接口的匿名局部類";
}
}
IClazzInner clazzInner1 = new ClazzInner();
System.out.println(clazzInner1.onTest2Inner());
//實現接口的方式的匿名內部類方式二
IClazzInner clazzInner2 = new IClazzInner() {
@Override
public String onTest2Inner() {
return "這是一個實現了IClazzInner接口的匿名類";
}
};
System.out.println(clazzInner2.onTest2Inner());
}
}