Java内部类简介.
一, 什么是內部類
Java中所謂內部類, 就是定義在另1個類內的類.
例如:
class A{int a;class B{int b;} }上面類B就是類A的一個內部類.
但是下面的寫法, B只是A的一個成員.
class A{private int a;B b; }class B{int bb; }因為B的定義體在類A之外, 注意區別.
Java編譯器編譯后, 還是會把面的代碼編譯成兩個class.
1個是A
另1個是 A$B
對于Jvm來講,它們實際上還是兩個單獨的類.
二,內部類的好處.
的確, 內部類的寫法的確會破壞Java代碼的良好結構以及可讀性.
但是內部類也有它存在的意義.
例如一部法拉利跑車類, 它里面包括了1個發動機, 而發動機本身也有很多方法(例如,啟動, 變速等). 所以發動機本身也是1個類.
但是法拉利的發動機技術很好, 為了技術機密保護, 法拉利本身不想外部知道發動機的細節, 就可以把發動機作為1個內部類.
也就是說, 外部不能直接實例化1個法拉利發動機, 用在別的車上.
好處:
1. 限制外部世界對內部類的訪問.
2. 內部類可以直接訪問外部類的成員.
其中第2點很重要, 甚至比第一點還重要.
三,什么情況下需要用到內部類.
這里我舉1個具體點的例子.
加入1個聊天窗口Form類.
有很多控件類對象成員(例如輸入框, 顯示框等).
現在要啟動2個線程, 分別用于接受和發送消息.
問題來了, 啟動線程必須要重寫Thread類或實現Runable接口,總結要寫新的類.
那么新的類寫在哪里呢.
如果寫在外面, 那么新的類必須寫入很多控件類的成員.
如果寫入在Form類里面, 就可以直接使用Form類的所有成員. 這樣就方便很多.
而且這個兩個類也不想被其他類使用, 所以內部類就很適合了.
四,內部類的種類.
沒錯, Java內部類也可以根據定義的位置和訪問權限分成下面若干種內部類.
4.1 定義在另1個類的方法體外的內部類.
4.1.1 非私有內部類(非靜態)
這種內部i類(B)雖然定義在另1個類(A)的內部, 但實際上它是被第三個類(C)實例化的.
不過C類想實例化類B. 則必須先實例化類A.
public class InternalClass1{public static void f(){A a = new A(3);A.B b = a.new B();b.print();A.B b2 = new A(4).new B();b2.print();} }class A{private int i;public A(int i){this.i = i;}class B{public void print(){System.out.printf("A.i is %d\n",i);}} }上面的例子定義了外部類A和內部類B.
可以見到內部類B是無限制地訪問A的私有成員的.
反過來, 類A也同樣可以無限制的內部類B的私有成員.?
而B可以被第三個類(InternalClass1)實例化.
實例化的寫法上面寫了兩種, 但是都必須事先實例化1個A對象.
也就是說Java必須為A的1個對象分配內存, 才能為A的內部類對象分配內存.
4.1.2 私有內部類(非靜態)
私有內部類指的是private 修飾的內部類(注意外部類不能被private修飾)
這樣的話
內部類B不能被第三方類C直接訪問和實例化
但是能通過A的封裝方法訪問.
例子:
4.1.3 靜態內部類
跟外部類不同, 內部類可以用static關鍵字來修飾. 代表這個是1個靜態內部類.
靜態內部類跟非靜態內部類有兩點不同.
1. 實例化1個非靜態內部類之前必須實例化其外部類.?? 而靜態內部類不需要. 可以直接被實例化, 也就是說靜態內部類不需要1個外部類對象.
2. 同樣地, 內部類只能訪問其外部類的靜態成員.? 因為外部類的非靜態成員依賴于外部類對象實例化.
例子:
public class InternalClass3{public static void f(){A3.printj(3);} }class A3{private int i;private static int j;public static void printj(int j){B3 b = new B3(j);b.print();}private static class B3{public B3(int j){//A3.i= 3;//errorA3.j = j;}public void print(){System.out.printf("A.j is %d\n",j);}} }4.1.4 方法體內部類
下面開始惡心了,? 就是內部類可以定義在方法體內.
假如B 是 A的方法f(int a)內的1個內部類.
1. B還是無限制訪問A的所有成員.
2. A只能在方法f()內訪問和使用B.
?? 假如B定義在f() 里面的if() 或 try{}字句內, 那么同樣地, A只能在if,try的作用范圍內使用B.
3. 在方法體f()內, 代碼還是嚴格按照順序執行的, 那就是說必須先定義內部體B, 再使用.
4. 假如B定義的內部使用到參數a 那么a必須用Final修飾.
例子:
public class InternalClass4{public static void f(){new A4(2).printB(3,6);} }class A4{private int i;public A4(int i){this.i = i;}public void printB(final int x, int y){//class Bclass B4{public int getSum(){return i + x;}} System.out.println(new B4().getSum() + y);} }例如上面的printB方法,? 有兩個參數x, y 但是內部類B只訪問了x, 所以x必須用final修飾, 而y不用.
可以看出, 這個種內部類已經大大影響java代碼的可讀性了.
幸好這種內部類不可能被其他類訪問. 作用域也只在方法體內. 但是起名字還是需要避免和同包內的其它類沖突.
4.1.5 匿名內部類
所謂匿名內部類就是定義1個內部類時不指定類名字
聽起來不合常理啊.
在外部類A內定義1個匿名內部類B(注意B不是類名, 只是1個代號) 有兩個必要天劍.
1.內部類B只能定義在A的方法體內.
2.內部類必須是繼承自另1個類Bp(Bp是類名).? 或者是實現另1個接口Bi(Bi是接口名).
而Bp和Bi必須事先定義.
對于第一種, 一般用于調用1個超類的重寫工公共方法..? 例如重寫Thread類Run方法, 開啟1個新進程.
對于第2種, 一般是返回1個接口的實現類對象:
例如:
public class InternalClass6{public static void f(){Ib b = new A6().GetIB(4);b.f();} }class A6{private int i = 100;public Ib GetIB(final int x){//a new internal class which implements interface Ib return new Ib(){public void f(){System.out.println("this is a method implemented from a interface!");System.out.println(i+x);}};} }interface Ib{void f(); }注意這個接口必須是事先定義的.
匿名內部類的好處是隨寫隨用, 而且無非擔心命名沖突.
總結
以上是生活随笔為你收集整理的Java内部类简介.的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 接口(interface)的用
- 下一篇: 简单工厂(SimpleFactory)模