前言 由於平時使用內部類不多,所以對內部類只有一個很淺的認知。趁著春節有空,整理了一些內部類的使用筆記。 使用內部類的好處 使用內部類可以很好地解決多重繼承的問題,每個內部類都能獨立地繼承一個(介面的)實現。 內部類的分類 成員內部類 靜態內部類 方法內部類 匿名內部類 1.成員內部類 privat ...
前言
由於平時使用內部類不多,所以對內部類只有一個很淺的認知。趁著春節有空,整理了一些內部類的使用筆記。
使用內部類的好處
使用內部類可以很好地解決多重繼承的問題,每個內部類都能獨立地繼承一個(介面的)實現。
內部類的分類
成員內部類
靜態內部類
方法內部類
匿名內部類
1.成員內部類
private int num = 100;
String name = "zhou";
public class Inner{
String name = "Inner Zhou";
public void print(){
System.out.println(Demo.this.name); //當內部類屬性名和外部類屬性名一樣時,外部類需要(外部類.this.屬性)來調用
System.out.println(name);//當內部類屬性名和外部類屬性名一樣時,預設調用內部類屬性
System.out.println(num);
}
}
public static void main(String[] args){
Demo o = new Demo();
Inner in = o.new Inner();
in.print();
}
}
- 成員內部類可以使用任意訪問控制符,如 public 、 protected 、 private 等。
- 外部類可以直接訪問成員內部類中的數據,而不受訪問控制符的影響,如直接訪問Demo類中的私有屬性num。
- 當成員內部類的屬性名和外部類的屬性名一樣時,預設調用成員內部類屬性。如上面代碼中,Demo類中的name屬性與Inner中name屬性名稱一樣,那麼System.out.println(name);是預設調用的是Inner的name屬性。
- 成員內部類必須使用外部類對象來創建成員內部類對象,而不能直接去 new 一個內部類對象。即:內部類 對象名 = 外部類對象.new 內部類( )。
- 上述編譯程式後,會產生了兩個 .class 文件: Demo.class,Demo$Inner.class{}。
- 成員內部類中不能存在任何static 的變數和方法,可以定義常量。
2.靜態內部類
private int num = 100;
String str = "zhou";
static String name = "zhou";
public static class Inner{
String name = "Inner Zhou";
public void print(){
System.out.println(new Demo().str);
System.out.println(Demo.name);
System.out.println(name);
}
}
public static void main(String[] args){
Inner in = new Inner();
in.print();
}
}
- 靜態內部類不能直接訪問外部類的非靜態成員,但可以通過【new 外部類().成員】 的方式訪問
- 如果外部類的靜態成員與內部類的成員名稱相同,可通過【類名.靜態成員】訪問外部類的靜態成+ 員,否則可通過【成員名】直接調用外部類的靜態成員。
- 創建靜態內部類的對象時,可以直接創建 內部類 對象名 = new 內部類();
3.方法內部類
String a = "zhou a";
public void show() {
String b = "Zhou b";
class Inner {
String c = "Zhou c";
public void print(){
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
Inner i = new Inner();
i.print();
}
public static void main(String[] args) {
Demo demo = new Demo();
demo.show();
}
}
- 方法內部類不能有 public、protected、private 以及 static 修飾符
- jdk8版本之前,只能訪問方法中定義的 final 類型的局部變數。
- jdk1.8版本之後,新增了 Effectively final功能,方法內部類和匿名內部類中調用方法中的局部變數,可以不需要修飾為 final。下麵是文檔的原話:
However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final.
- 4.反編譯jdk8編譯之後的class文件,內部類引用外部的局部變數都是 final 修飾的。
4.匿名內部類
public InnerClass getInnerClass(String str){
return new InnerClass(){
{
a = 2; //利用構造代碼塊能夠達到為匿名內部類創建一個構造器的效果
}
public String getStr(){
return str;
}
};
}
abstract class InnerClass {
int a;
abstract String getStr();
}
//也可以是介面
/*interface InnerClass{
String getStr();
}*/
public static void main(String[] args) {
Demo demo = new Demo();
InnerClass inner = demo.getInnerClass("zhou");
System.out.println(inner.getStr());
System.out.println(inner.a);
}
}
- 創建匿名內部類時它會立即創建一個該類的實例。
- 使用匿名內部類時,必須繼承一個類或者實現一個介面,但同時也只能繼承一個類或者實現一個介面。
- 匿名內部類中不能定義構造函數,不能存在任何的靜態成員變數和靜態方法。
- 匿名內部類不能是抽象的,它必須要實現繼承的類或者實現的介面的所有抽象方法。
- 匿名內部類初始化:可以使用構造代碼塊達到為匿名內部類創建一個構造器的效果。