java内部类实现方式_Java内部类详解
一 內部類是什么
Java類中不僅可以定義變量和方法,還可以定義類,這樣定義在類內部的類就被稱為內部類。根據定義的方式不同,內部類分為靜態內部類,成員內部類,局部內部類,匿名內部類四種。
Java為什么要引入內部類這個概念呢?原因在于,內部類定義在類的內部,可以方便訪問外部類的變量和方法,并且和其它類進行隔離。
二 靜態內部類
定義在類內部的靜態類,就是靜態內部類。
2.1 語法
定義一個靜態內部類:
public class Out {
private static int a;
private int b;
public static class Inner {
public void print() {
System.out.println(a);
}
}
}
Inner就是靜態內部類。靜態內部類可以訪問外部類所有的靜態變量和方法,即使是private的也一樣。靜態內部類和一般類一致,可以定義靜態變量、方法,構造方法等。
其它類使用靜態內部類需要使用“外部類.靜態內部類”方式,如下所示:
Out.Inner inner = new Out.Inner();
inner.print();
2.2 實現原理
查看編譯后的代碼可以知道,Out.java編譯后會生成兩個class文件,分別是Out.class和Out$Inner.class。因為這兩個類處于同一個包下,所以靜態內部類自然可以訪問外部類的非私有成員。但是我們知道靜態內部類是可以訪問外部類所有訪問權限的成員的,Java是如何實現的呢?看編譯后生成的代碼就知道了:
public class Out$Inner {
public Out$Inner() {
}
public void print() {
System.out.println(Out.access$000());
}
}
靜態內部類通過外部類的access$000()方法訪問外部類的私有變量,這個方法是編譯器自動生成的。在運行時,我們可以通過反射調用該方法。
2.3 應用場景
Java集合類HashMap內部就有一個靜態內部類Entry。Entry是HashMap存放元素的抽象,HashMap內部維護Entry數組用了存放元素,但是Entry對使用者是透明的。像這種和外部類關系密切的,且不依賴外部類實例的,都可以使用靜態內部類。
三 成員內部類
定義在類內部的非靜態類,就是成員內部類。
3.1 語法
定義一個成員內部類:
public class Out {
private static int a;
private int b;
public class Inner {
public void print() {
System.out.println(a);
System.out.println(b);
}
}
}
成員內部類可以訪問外部類所有的變量和方法,包括靜態和實例,私有和非私有。和靜態內部類不同的是,每一個成員內部類的實例都依賴一個外部類的實例。其它類使用內部類必須要先創建一個外部類的實例。如下所示:
Out out = new Out();
Out.Inner inner = out.new Inner();
inner.print();
成員內部類不能定義靜態方法和變量(final修飾的除外)。這是因為成員內部類是非靜態的,類初始化的時候先初始化靜態成員,如果允許成員內部類定義靜態變量,那么成員內部類的靜態變量初始化順序是有歧義的。
3.2 實現原理
和靜態內部類類似,Out.java編譯后會生成兩個class文件,分別是Out.class和Out$Inner.class。成員內部類的代碼如下:
public class Out$Inner {
public Out$Inner(Out var1) {
this.this$0 = var1;
}
public void print() {
System.out.println(Out.access$000());
}
}
成員內部類訪問外部類的私有變量和方法也是通過編譯時生成的代碼訪問的。區別是,成員內部類的構造方法會添加一個外部類的參數。
四 局部類
定義在方法中的類,就是局部類。
4.1 語法
定義一個局部類:
public class Out {
private static int a;
private int b;
public void test(final int c) {
final int d = 1;
class Inner {
public void print() {
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
}
public static void testStatic(final int c) {
final int d = 1;
class Inner {
public void print() {
System.out.println(a);
//定義在靜態方法中的局部類不可以訪問外部類的實例變量
//System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
}
}
局部類只能在定義該局部類的方法中使用。定義在實例方法中的局部類可以訪問外部類的所有變量和方法,定義在靜態方法中的局部類只能訪問外部類的靜態變量和方法。同時局部類還可以訪問方法的參數和方法中的局部變量,這些參數和變量必須要聲明為final的。
4.2 實現原理
Out.java編譯后局部類會生成相應的class文件。
class Out$1Inner {
Out$1Inner(Out var1, int var2) {
this.this$0 = var1;
this.val$c = var2;
}
public void print() {
System.out.println(Out.access$000());
System.out.println(Out.access$100(this.this$0));
System.out.println(this.val$c);
System.out.println(1);
}
}
和成員內部類類似,生成的局部類的構造方法包含了外部類的參數,并且還包含了定義局部類方法的參數,這也就解釋了為什么局部類可以訪問外部類和方法的成員。同時也明白了為什么局部類訪問的變量需要final修飾,因為局部類訪問的變量其實是該局部類自己的成員,如果不用final修飾,那么在局部類修改該變量的值并不會影響方法中該變量的值。為了避免這種困惑,Java就禁止修改。
4.3 應用場景
如果一個類只在某個方法中使用,則可以考慮使用局部類。
五 匿名內部類
5.1 語法
定義一個匿名內部類:
public class Out {
private static int a;
private int b;
private Object obj = new Object() {
private String name = "匿名內部類";
@Override
public String toString() {
return name;
}
};
public void test() {
Object obj = new Object() {
@Override
public String toString() {
System.out.println(b);
return String.valueOf(a);
}
};
System.out.println(obj.toString());
}
}
匿名內部類可以出現在任何允許表達式出現的地方,定義格式:
new 類/接口{
//匿名內部類實現部分
}
5.2 實現原理
Out.java編譯后匿名內部類會生成相應的class文件。
class Out$1 {
private String name;
Out$1(Out var1) {
this.this$0 = var1;
this.name = "匿名內部類";
}
public String toString() {
return this.name;
}
}
匿名內部類可以訪問外部類所有的變量和方法。
5.3 應用場景
匿名內部類使用廣泛,比如我們常用的綁定監聽的時候。
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"click",Toast.LENGTH_SHORT).show(); }
});
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的java内部类实现方式_Java内部类详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python如何实时捕捉cmd显示_如何
- 下一篇: php连接数据库性能测试,无需安装配置,