標籤:java 內部類
1.普通的內部類(內部類非static)
內部類可以訪問外圍對象的所有成員,某個外圍類對象建立一個內部類對象時,此內部類對象會捕獲一個指向外圍類的引用。然後在訪問外圍類的成員時,就是用那個引用來選擇外圍類的成員。編譯器訪問不到這個引用就會報錯。
普通內部類不能有static的屬性和方法,若有則要使用嵌套類。
class Outer{public class Inner{}Inner in = new Inner();// 包含了這個外部對象的引用為this}public class Test{public static void main(String[] args) {//Outer outer = new Outer();//Outer.Inner in = outer.new Inner();// 這兩句和下面完全等價Outer.Inner in = new Outer().new Inner();}}
注意:Outer.Inner in = new Outer().new Inner(); 當導包的時候匯入到具體的內部類時就可以寫成Inner in = new Outer().new Inner();否則就要把外部類帶上。在new對象的時候必須先得到外圍類的對象的引用。
2.匿名內部類
下面的例子將返回值的產生和表示這個返回值類型的定義結合在一起,他沒有名字。在建立A對象的的時候,A實際是一個介面,並不能直接new對象,因此要實現未實現的方法,實際上就是實現了一個介面的類對象然後被向上轉型成父類的引用。
使用匿名內部類時,如要在其內部使用外部定義的對象,那麼該參數引用必須是final的。
interface A{public void method();}class AImp implements A{public void method(){System.out.println("AImp");}}class Test{private static A getA(){//return new A() {//public void method() {//System.out.println("Aimp_Test");//}//};return new AImp();}public static void main(String[] args) {getA().method();;}}
3.嵌套類
如果不需要內部類對象與其外為對象之間有聯絡,就可以將內部類聲明為static。不同的內部類對象隱式的儲存了一個指向它外為對象的引用。嵌套類在建立對象時不需要外圍類對象,但是嵌套類裡面不能訪問外圍類中的非靜態屬性和方法。
Android中的廣播接收者在使用靜態聲明的時候就要求為靜態嵌套類,不然找不到該類。
class Outer{private int x;public static class Inner{//int y = x;// error}Inner in = new Inner();}public class Test{public static void main(String[] args) {Outer.Inner in = new Outer.Inner();}}
Android中如下使用Handler,會警告ThisHandler class should be static or leaks might occur,Handler類應該是靜態,否則會記憶體泄露,原因就是建立MyHandler這個內部類的時候,還保留了一個對外部類的引用,一般是Activity,一旦activity被銷毀,就會出問題。
class MyHandler extends Handler{public void handleMessage(android.os.Message msg) {switch (msg.what) {}};};private Handler handler = new MyHandler();
4.內部類向上轉型為介面——暴露/隱藏部分實現
class B{private void f(){System.out.println("f()");}private void g(){System.out.println("g()");}public class AImp{public void method1(){f();}public void method2(){g();}}}public class Test{public static void main(String[] args) {B b = new B();AImp aImp = b.new AImp();aImp.method1();aImp.method2();}}
由於AImp是public的,因此就可以訪問到它,也就能訪問他的所有方法。下面使用介面來只暴露method1函數。向上轉型為一個介面就可以在這裡介面裡放想要暴露的函數。
interface A{void method1();}class B{private void f(){System.out.println("f()");}private void g(){System.out.println("g()");}public A getA(){return new AImp();}private class AImp implements A{public void method1(){f();}public void method2(){g();}}}public class Test{public static void main(String[] args) {B b = new B();//AImp aImp = b.new AImp(); // 由於AImp是private的 errorA aImp = b.getA();// b.getA()向上轉型,轉型為一個介面 就可以在這裡介面裡放想要暴露的函數。aImp.method1(); // 只暴露menthod1// aImp.method2(); // The method method2() is undefined for the type A}}
JAVA內部類