Java內部類總結1

Java內部類總結2007-08-22 來自:lizhe1985  [收藏到我的網摘]內部類是指在一個外部類的內部再定義一個類。內部類作爲外部類的一個成員,並且依附於外部類而存在的。內部類可爲靜態,可用protected和 private修飾(而外部類只能使用public和缺省的包訪問權限)。內部類主要有以下幾類:成員內部類、局部內部類、靜態內部類、匿名內部類
­
  爲什麼需要內部類?
­
  典型的情況是,內部類繼承自某個類或實現某個接口,內部類的代碼操作創建其的外圍類的對象。所以你可以認爲內部類提供了某種進入其外圍類的窗口。使用內部類最吸引人的原因是:
­
  每個內部類都能獨立地繼承自一個(接口的)實現,所以無論外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。如果沒有內部類提供的可以繼承多個具體的或抽象的類的能力,一些設計與編程問題就很難解決。從這個角度看,內部類使得多重繼承的解決方案變得完整。接口解決了部分問題,而內部類有效地實現了“多重繼承”。
­
  A:成員內部類
­
  作爲外部類的一個成員存在,與外部類的屬性、方法並列。
­
publicclass Outer {
privatestaticinti = 1;
privateintj = 10;
privateintk = 20;
­
publicstaticvoidouter_f1() {
}
­
publicvoidouter_f2() {
}
­
// 成員內部類中,不能定義靜態成員
// 成員內部類中,可以訪問外部類的所有成員
class Inner {
// static int inner_i = 100; //內部類中不允許定義靜態變量
intj = 100; // 內部類和外部類的實例變量可以共存
intinner_i = 1;
­
void inner_f1() {
System.out.println(i);
//在內部類中訪問內部類自己的變量直接用變量名
System.out.println(j);
//在內部類中訪問內部類自己的變量也可以用this.變量名
System.out.println(this.j);
//在內部類中訪問外部類中與內部類同名的實例變量用外部類名.this.變量名
System.out.println(Outer.this.j);
//如果內部類中沒有與外部類同名的變量,則可以直接用變量名訪問外部類變量
System.out.println(k);
outer_f1();
outer_f2();
}
}
­
//外部類的非靜態方法訪問成員內部類
publicvoidouter_f3() {
Inner inner = new Inner();
inner.inner_f1();
}
­
// 外部類的靜態方法訪問成員內部類,與在外部類外部訪問成員內部類一樣
publicstaticvoidouter_f4() {
//step1 建立外部類對象
Outer out = new Outer();
//step2 根據外部類對象建立內部類對象
Inner inner = out.new Inner();
//step3 訪問內部類的方法
inner.inner_f1();
}
­
publicstaticvoid main(String[] args) {
//outer_f4(); //該語句的輸出結果和下面三條語句的輸出結果一樣
//如果要直接創建內部類的對象,不能想當然地認爲只需加上外圍類Outer的名字,
//就可以按照通常的樣子生成內部類的對象,而是必須使用此外圍類的一個對象來
//創建其內部類的一個對象:
//Outer.Inner outin = out.new Inner()
//因此,除非你已經有了外圍類的一個對象,否則不可能生成內部類的對象。因爲此
//內部類的對象會悄悄地鏈接到創建它的外圍類的對象。如果你用的是靜態的內部類,
//那就不需要對其外圍類對象的引用。
Outer out = new Outer();
Outer.Inner outin = out.new Inner();
outin.inner_f1();
}
}
­
  注意:內部類是一個編譯時的概念,一旦編譯成功,就會成爲完全不同的兩類。對於一個名爲outer的外部類和其內部定義的名爲inner的內部類。編譯完成後出現outer.class和outer$inner.class兩類。
­
  B:局部內部類
­
  在方法中定義的內部類稱爲局部內部類。與局部變量類似,局部內部類不能有訪問說明符,因爲它不是外圍類的一部分,但是它可以訪問當前代碼塊內的常量,和此外圍類所有的成員。
­
publicclass Outer {
privateints = 100;
privateintout_i = 1;
­
publicvoid f(finalint k) {
finalint s = 200;
int i = 1;
finalint j = 10;
­
//定義在方法內部
class Inner {
ints = 300; // 可以定義與外部類同名的變量
­
// static int m = 20; //不可以定義靜態變量
Inner(int k) {
inner_f(k);
}
­
intinner_i = 100;
­
voidinner_f(int k) {
//如果內部類沒有與外部類同名的變量,在內部類中可以直接訪問外部類的實例變量
System.out.println(out_i);
//可以訪問外部類的局部變量(即方法內的變量),但是變量必須是final的
System.out.println(j);
//System.out.println(i);
//如果內部類中有與外部類同名的變量,直接用變量名訪問的是內部類的變量
System.out.println(s);
//用this.變量名訪問的也是內部類變量
System.out.println(this.s);
//用外部類名.this.內部類變量名訪問的是外部類變量
System.out.println(Outer.this.s);
}
}
new Inner(k);
}
­
publicstaticvoid main(String[] args) {
// 訪問局部內部類必須先有外部類對象
Outer out = new Outer();
out.f(3);
}
}
­
  C:靜態內部類(嵌套類):(注意:前兩種內部類與變量類似,所以可以對照參考變量)
­
  如果你不需要內部類對象與其外圍類對象之間有聯繫,那你可以將內部類聲明爲static。這通常稱爲嵌套類(nested class)。想要理解static應用於內部類時的含義,你就必須記住,普通的內部類對象隱含地保存了一個引用,指向創建它的外圍類對象。然而,當內部類是static的時,就不是這樣了。嵌套類意味着:
­
  1. 要創建嵌套類的對象,並不需要其外圍類的對象。
  2. 不能從嵌套類的對象中訪問非靜態的外圍類對象。
­
publicclass Outer {
privatestaticinti = 1;
privateintj = 10;
publicstaticvoidouter_f1() {
}
­
publicvoidouter_f2() {
}
­
// 靜態內部類可以用public,protected,private修飾
// 靜態內部類中可以定義靜態或者非靜態的成員
staticclass Inner {
staticintinner_i = 100;
intinner_j = 200;
staticvoidinner_f1() {
//靜態內部類只能訪問外部類的靜態成員(包括靜態變量和靜態方法)
System.out.println("Outer.i" + i);
outer_f1();
}
­
voidinner_f2() {
// 靜態內部類不能訪問外部類的非靜態成員(包括非靜態變量和非靜態方法)
// System.out.println("Outer.i"+j);
// outer_f2();
}
}
­
publicvoidouter_f3() {
// 外部類訪問內部類的靜態成員:內部類.靜態成員
System.out.println(Inner.inner_i);
Inner.inner_f1();
// 外部類訪問內部類的非靜態成員:實例化內部類即可
Inner inner = new Inner();
inner.inner_f2();
}
­
publicstaticvoid main(String[] args) {
newOuter().outer_f3();
}
}
­
  生成一個靜態內部類不需要外部類成員:這是靜態內部類和成員內部類的區別。靜態內部類的對象可以直接生成:Outer.Inner in = new Outer.Inner(); 而不需要通過生成外部類對象來生成。這樣實際上使靜態內部類成爲了一個頂級類(正常情況下,你不能在接口內部放置任何代碼,但嵌套類可以作爲接口的一部分,因爲它是static 的。只是將嵌套類置於接口的命名空間內,這並不違反接口的規則)
­
  D:匿名內部類(from thinking in java 3th)
­
  簡單地說:匿名內部類就是沒有名字的內部類。什麼情況下需要使用匿名內部類?如果滿足下面的一些條件,使用匿名內部類是比較合適的:
­
  ·只用到類的一個實例。
  ·類在定義後馬上用到。
  ·類非常小(SUN推薦是在4行代碼以下)
  ·給類命名並不會導致你的代碼更容易被理解。
  在使用匿名內部類時,要記住以下幾個原則:
  ·匿名內部類不能有構造方法。
  ·匿名內部類不能定義任何靜態成員、方法和類。
  ·匿名內部類不能是public,protected,private,static。
  ·只能創建匿名內部類的一個實例。
·一個匿名內部類一定是在new的後面,用其隱含實現一個接口或實現一個類。
  ·因匿名內部類爲局部內部類,所以局部內部類的所有限制都對其生效。
­
  下面的例子看起來有點奇怪:
­
//在方法中返回一個匿名內部類
public class Parcel6 {
public Contents cont() {
return new Contents() {
private int i = 11;
­
public int value() {
return i;
}
}; // 在這裏需要一個分號
}
­
public static void main(String[] args) {
Parcel6 p = new Parcel6();
Contents c = p.cont();
}
}
­
  cont()方法將下面兩個動作合併在一起:返回值的生成,與表示這個返回值的類的定義!進一步說,這個類是匿名的,它沒有名字。更糟的是,看起來是你正要創建一個Contents對象:
­
return new Contents()
­
  但是,在到達語句結束的分號之前,你卻說:“等一等,我想在這裏插入一個類的定義”:
­
return new Contents() {
private int i = 11;
public int value() { return i; }
};
­
  這種奇怪的語法指的是:“創建一個繼承自Contents的匿名類的對象。”通過new 表達式返回的引用被自動向上轉型爲對Contents的引用。匿名內部類的語法是下面例子的簡略形式:
­
class MyContents implements Contents {
private int i = 11;
public int value() { return i; }
}
return new MyContents();
 
發佈了9 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章