一、內部類別:
(1)內部類別的同名方法
內部類別可以呼叫外層類別的方法,如果內部類別有同名方法必須使用"OuterClass.this.MethodName()"格式呼叫(其中OuterClass與MethodName換成實際外部類別名稱及其方法;this為關鍵字,表示外部類別的參考);若內部類別無同名方法可以直接呼叫外圍類別的方法。
但外圍類別無法直接呼叫內部類別的private方法,外部類別同樣無法直接呼叫其它類別的private方法。注意:內部類別直接使用外部類別的方法與該方法的權限與是否static無關,它取決於內部類別是否有同名方法。
package innerclass; public class OuterClass { private void outerMethod() { System.out.println("It's Method of OuterClass"); } public static void main(String[] args) { OuterClass t = new OuterClass(); OuterClass.Innerclass in = t.new Innerclass(); in.innerMethod(); } class Innerclass { public void innerMethod() { OuterClass.this.outerMethod();// 内部类成员方法与外部类成员方法同名时,使用this调用外部类的方法 outerMethod();// 内部类没有同名方法时执行外部类的方法 } private void outerMethod() { System.out.println("It's Method of Innerclass"); } } }
輸出結果為:
It's Method of OuterClass It's Method of Innerclass
(2)內部類別的實例化
內部類別實例化不同於普通類,普通類別可以在任意需要的時候實例化,而內部類別必須在外層類別實例化以後方可實例化,並與外部類別建立關係
因此在外部類別中的非static方法中,是可以實例化內部類別物件
private void outerMethod() { System.out.println("It's Method of OuterClass"); Innerclass in = new Innerclass();//在外部类的outerMethod方法中实例化内部类是可以啊 }
但在static方法中,就要注意! ! ! !不能在static方法中直接new內部類,否則出現錯誤:
No enclosing instance of type OuterClass is accessible. Must qualify the allocation with an enclosing instance of type OuterClass (e.g. x. A(insta) wh: new instance. OuterClass).
這是因為靜態方法是在類別實例化之前就可以使用的,透過類別名稱調用,這時動態內部類別都還沒實例化呢,怎麼用,總不能調用一個不存在的東西吧。
如果想在Static方法中new內部類,可以把內部類別宣告為Static
public class OuterClass { private void outerMethod() { System.out.println("It's Method of OuterClass"); } public static void main(String[] args) { Innerclass in = new Innerclass(); in.innerMethod(); } static class Innerclass {//把内部类声明为static public void innerMethod() { System.out.println("It's Method of innerMethod"); } } }
當然,一般不使用static的方式,而是推薦這種方法:x.new A() ,其中x是外部類OuterClass的實例,A是內部類別Innerclass
package innerclass; public class OuterClass { private void outerMethod() { System.out.println("It's Method of OuterClass"); } public static void main(String[] args) { OuterClass.Innerclass in = new OuterClass().new Innerclass();//使用x.new A()的方式 in.innerMethod(); } class Innerclass { public void innerMethod() { System.out.println("It's Method of innerMethod"); } } }
x.new A() ,其中x是外部類別OuterClass的實例,A是類別部類別Innerclass,當然可以分割如下,這樣就顯然很明白:
public static void main(String[] args) { OuterClass out = new OuterClass();//外部实例 OuterClass.Innerclass in = out.new Innerclass();//外部实例.new 外部类 in.innerMethod(); }
(3)什麼情況下使用內部類別
典型的情況是,內部類別繼承自某個類別或實作某個接口,內部類別的程式碼操作建立其的外層類別的物件。所以你可以認為內部類別提供了某種進
入其外層類別的視窗。
使用內部類別最吸引人的原因是:每個內部類別都能獨立地繼承自一個(介面的)實現,所以無論外層類別是否已經繼承了某個(介面的)實
現,對於內部類別都沒有影響。如果沒有內部類別提供的可以繼承多個具體的或抽象的類別的能力,一些設計與程式設計問題就很難解決。從這個角
度看,內部類別使得多重繼承的解決方案變得完整。介面解決了部分問題,而內部類別有效地實現了「多重繼承」。
(4)在靜態方法中實例化內部類別範例:(內部類別放在靜態方法中)
package javatest2; public class JavaTest2 { public static void main(String[] args) { class Boy implements Person { public void say() {// 匿名内部类自定义的方法say System.out.println("say方法调用"); } @Override public void speak() {// 实现接口的的方法speak System.out.println("speak方法调用"); } } Person per = new Boy(); per.speak();// 可调用 per.say();// 不能调用 } } interface Person { public void speak(); }
per.speak()可調用,而per.say()不能調用,這時因為per是Person對象,要呼叫子類別的方法,可以強制向下轉型為:((Boy) per).say();或直接改為Boy per = new Boy();。從中可發現,若要呼叫內部類別的自訂的方法,必須透過內部類別的物件來呼叫。那麼,匿名內部類別連名字都沒有,怎麼呼叫內部類別自訂的方法呢?
(二)匿名內部類別
匿名內部類別也就是沒有名字的內部類別正因為沒有名字,所以匿名內部類別只能使用一次,它通常用來簡化程式碼編寫,但使用匿名內部類別還有個前提條件:必須繼承一個父類或實作一個接口,但最多只能繼承一個父類,或實作一個接口。
關於匿名內部類別還有以下兩條規則:
1)匿名內部類別不能是抽象類別,因為系統在建立匿名內部類別的時候,會立即建立內部類別的物件。因此不允許將匿名內部類別定義成抽象類別。
2)匿名內部類別不等定義建構器(建構方法),因為匿名內部類別沒有類別名,所以無法定義建構器,但匿名內部類別可以定義實例初始化區塊,
怎麼判斷一個匿名類別的存在啊?看不見名字,感覺只是父類別new出一個物件而已,沒有匿名類別的名字。
先看段偽代碼
abstract class Father(){ .... } public class Test{ Father f1 = new Father(){ .... } //这里就是有个匿名内部类 }
一般來說,new 一個物件時小括號後應該是分號,也就是new出物件該語句就結束了。但出現匿名內部類別就不一樣,小括號後面接的是大括號,大括號中是該new 出物件的具體的實作方法。因為我們知道,一個抽象類別是不能直接new 的,必須先有實作類別了我們才能new出它的實作類別。上面的偽代碼就是表示new 的是Father的實作類,這個實作類別是個匿名內部類別。
其實拆分上面的匿名內部類別可為:
class SonOne extends Father{ ... //这里的代码和上面匿名内部类,大括号中的代码是一样的 } public class Test{ Father f1 = new SonOne() ; }
先看一個例子,體會一下匿名內部類別的用法:
运行结果:eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了,这样便可以省略一个类的书写。并且,匿名内部类还能用于接口上
public class JavaTest2 { public static void main(String[] args) { Person per = new Person() { public void say() {// 匿名内部类自定义的方法say System.out.println("say方法调用"); } @Override public void speak() {// 实现接口的的方法speak System.out.println("speak方法调用"); } }; per.speak();// 可调用 per.say();// 出错,不能调用 } } interface Person { public void speak(); }
这里per.speak()是可以正常调用的,但per.say()不能调用,为什么呢?注意Person per = new Person()创建的是Person的对象,而非匿名内部类的对象。其实匿名内部类连名字都没有,你咋实例对象去调用它的方法呢?但继承父类的方法和实现的方法是可以正常调用的,本例子中,匿名内部类实现了接口Person的speak方法,因此可以借助Person的对象去调用。
若你确实想调用匿名内部类的自定义的方法say(),当然也有方法:
(1)类似于speak方法的使用,先在Person接口中声明say()方法,再在匿名内部类中覆写此方法。
(2)其实匿名内部类中隐含一个匿名对象,通过该方法可以直接调用say()和speak()方法;代码修改如下:
public class JavaTest2 { public static void main(String[] args) { new Person() { public void say() {// 匿名内部类自定义的方法say System.out.println("say方法调用"); } @Override public void speak() {// 实现接口的的方法speak System.out.println("speak方法调用"); } }.say();// 直接调用匿名内部类的方法 } } interface Person { public void speak(); }
更多内部类和匿名内部类的用法相关文章请关注PHP中文网!