java - 抽象類、接口、內部類

做者:eggjava

微博:http://weibo.com/xtfggef編程

出處:http://blog.csdn.net/zhangerqingide

 

抽象類與接口:ui

這兩個概念老是被放在一塊兒討論,由於他們有不少類似的地方,能夠說接口自己就是徹底抽象的,它要比抽象類更加「抽象」,爲何這麼說?抽象類是一種類,裏面除了有抽象方法外,還能夠有具體的方法,而接口裏面必須都是抽象的方法(有時能夠在接口裏定義類,後面會講),儘管有時並無顯示的用abstract關鍵字聲明。此處咱們提到抽象方法,在Java中,凡是聲明爲形如:abstract void function()的方法,都是抽象方法,包含抽象方法的類就是抽象類,能夠這麼總結:抽象類中是能夠沒有抽象方法的;有抽象方法的類必須是抽象類;抽象類不必定有實體方法。this

public class Run {.net

    public Runnable run22() {
        return new Runnable() {
            public void run() {
                System.out.println("run~~");
            }
        };
    }設計

    public static void main(String[] args) {
        new Run().run22().run();
    }
}
 htm

  1. public class B extends A {  
  2.   
  3.     @Override  
  4.     void a() {  
  5.         System.out.println();  
  6.     }  
  7.   
  8. }  
  9. abstract class A {  
  10.   
  11.     abstract void a();  
  12.     void b(){  
  13.           
  14.     }  
  15. }  

當咱們繼承抽象類時,必須重寫其抽象方法。由於上述緣由,因此抽象類不能被聲明爲final類型的,由於加final關鍵字的類保證不能被繼承,所以爲抽象類加final關鍵字,這個類就無法用了。抽象類只能被繼承,不能被實例化!對象

 

 

聲明爲interface的類爲接口,比抽象類更加抽象的一種機制。在接口中,咱們不能提供任何實現,全部方法必須都是抽象的,能夠不加abstract關鍵字,可是編譯器對於接口中的方法,都是直接按抽象方法處理的。咱們經過implements來實現某個接口。當咱們實現某個接口時,必須重寫其全部方法。blog

 

Java多繼承

以前咱們知道,採用interface爲咱們提供了一種將抽象與實現分離的結構化的方法,可是interface的做用遠不止此,在Java中接口解決了一個很是重要的問題:多繼承。在C++中,實現多重繼承是比較簡單的事兒,可是Java繼承機制不容許多重繼承,因此若是想要整合不一樣類的功能,就須要使用接口,咱們來看個例子:

  1. interface CanFight {void fight();}  
  2. interface CanFly {void fly();}  
  3. interface CanSwim {void swim();}  
  4. class ActionCharacter {public void fight(){}}  
  5. class Hero extends ActionCharacter implements CanFight, CanFly, CanSwim {  
  6.   
  7.     @Override  
  8.     public void swim() {}  
  9.   
  10.     @Override  
  11.     public void fly() { }  
  12.   
  13. }  
  14. public class Adventure {  
  15.       
  16.     public static void t(CanFight x){x.fight();}  
  17.       
  18.     public static void u(CanSwim x){x.swim();}  
  19.       
  20.     public static void v(CanFly x){x.fly();}  
  21.       
  22.     public static void w(ActionCharacter x){x.fight();}  
  23.       
  24.     public static void main(String[] args) {  
  25.         Hero h = new Hero();  
  26.         t(h);  
  27.         u(h);  
  28.         v(h);  
  29.         w(h);  
  30.     }  
  31. }  

咱們能夠看到:

一、Hero類中擁有了全部類的功能。

二、Hero能夠和它實現的這些接口進行相互轉換,當咱們將hero對象作參數,傳入Adventure類的各個方法時,Hero類向上轉型了。(此處咱們得出了一句話:在Java中,接口能夠和實現了該接口的類相互轉換)。講到此處,我想總結下使用接口的好處:

一、接口能夠實現向上轉型,多個具備共同屬性的類能夠將它們的共同點提取出來,作成抽象,這樣井井有條,統一管理。

二、接口不具備任何實現,最適合作基類。

總結一下抽象類與接口的區別和聯繫:

a)  抽象類是類,能夠有實體方法。

b)  抽象類不能實現多繼承,而接口能夠。

c)  若是須要建立不帶任何方法定義和成員變量的基類,則使用接口,若是類中須要有部分具體的實現,則使用抽象類。

d)  若是事先想要將某類設計爲一個基類,那麼首選接口。(注意c和d是接口的使用場景

接口能夠經過繼承(extends)接口,來拓展功能。接口中的域默認是final、static的,咱們能夠經過類名來直接引用。
內部類

 

建立:內部類的意思就是將類的定義放在另外一個類的內部。有時合理的內部類使用會使代碼更加簡潔,令程序更加巧妙。並且做爲外部類的成員,內部類能夠訪問外部類私有的成員變量。咱們先來看看內部類的建立,分這麼幾種狀況:

一、在外部類的非靜態方法中建立內部類的實例。

 

  1. public class InnerClass {  
  2.     class A{  
  3.         int a = 10;  
  4.         void b(){  
  5.             System.out.println("this is A.b()!");  
  6.         }  
  7.     }  
  8.       
  9.     void build(){  
  10.         A a = new A();  
  11.         a.b();  
  12.     }  
  13.       
  14.     public static void main(String[] args) {  
  15.         InnerClass ic = new InnerClass();  
  16.         ic.build();  
  17.     }  
  18. }  

 

 

二、在外部類的靜態方法中建立內部類的實例。

當在外部類的靜態方法中建立內部類時,當內部類是靜態的:

 

  1. public class InnerClass {  
  2.     static class A{  
  3.         int a = 10;  
  4.         void b(){  
  5.             System.out.println("this is A.b()!");  
  6.         }  
  7.     }  
  8.       
  9.     public static void main(String[] args) {  
  10.         InnerClass.build();  
  11.     }  
  12.       
  13.     static void build(){  
  14.         A a = new A();  
  15.         a.b();  
  16.     }  
  17. }  

當內部類是非靜態的:

 

  1. public class InnerClass {  
  2.     class A{  
  3.         int a = 10;  
  4.         void b(){  
  5.             System.out.println("this is A.b()!");  
  6.         }  
  7.     }  
  8.       
  9.     public static void main(String[] args) {  
  10.         InnerClass ic = new InnerClass();  
  11.         InnerClass.A aa = ic.new A();  
  12.         aa.b();  
  13.     }  
  14. }  

三、在內部類的非靜態方法中建立外部類的實例。(使用外部類.this來建立外部類的實例)

 

  1. public class InnerClass {  
  2.     class A{  
  3.         int a = 10;  
  4.         void build(){  
  5.             InnerClass ic = InnerClass.this;  
  6.             ic.a();  
  7.         }  
  8.     }  
  9.       
  10.     void a(){  
  11.         System.out.println("this is InnerClass.a()!");  
  12.     }  
  13. }  

四、在內部類的靜態方法中建立外部類的實例。(直接經過new來建立)

 

  1. public class InnerClass {  
  2.     static class A{  
  3.         int a = 10;  
  4.         static void build(){  
  5.             InnerClass ic = new InnerClass();  
  6.             ic.a();  
  7.         }  
  8.     }  
  9.       
  10.     void a(){  
  11.         System.out.println("this is InnerClass.a()!");  
  12.     }  
  13. }  

五、在其它類中建立內部類實例。(重點)

 

  1. public class InnerClass {  
  2.     class A{  
  3.         void a(){  
  4.             System.out.println("this is A.a()!");  
  5.         }  
  6.     }  
  7.     static class C{  
  8.         void c(){  
  9.             System.out.println("this is C.c()!");  
  10.         }  
  11.     }  
  12. }  
  13. class B{  
  14.     public static void main(String[] args){  
  15.         /*建立非靜態內部類*/  
  16.         InnerClass ic = new InnerClass();  
  17.         A a = ic.new A();  
  18.         a.a();  
  19.           
  20.         /*建立靜態內部類*/  
  21.         C c = new C();  
  22.         c.c();  
  23.     }  
  24. }  

來看個深層嵌套的:

 

  1. public class ABC {  
  2.     void a() {  
  3.         System.out.println("this is A.a()!");  
  4.     }  
  5.   
  6.     class B {  
  7.         void b() {  
  8.             System.out.println("this is B.b()!");  
  9.         }  
  10.   
  11.         class C {  
  12.             void c() {  
  13.                 a();  
  14.                 b();  
  15.                 System.out.println("this is C.c()!");  
  16.             }  
  17.         }  
  18.     }  
  19.   
  20.     public static void main(String[] args) {  
  21.         ABC abc = new ABC();  
  22.         ABC.B b = abc.new B();  
  23.         ABC.B.C c = b.new C();  
  24.         c.c();  
  25.     }  
  26. }  

感受愈來愈有意思了!此處最重要的就是這個」.new」操做符。同時,在類C內部調用a()和b()都很輕鬆,就說明內部類就至關於一個普通的變量,哪怕是private權限的,也同樣,直接調用,由於它們在同一個類中。匿名內部類的建立:

 

  1. interface A {  
  2.     void a();  
  3. }  
  4.   
  5. public class InnerClass_NoName {  
  6.   
  7.     public A test() {  
  8.         return new A() {  
  9.             public void a() {  
  10.                 System.out.println("");  
  11.             }  
  12.         };  
  13.     }  
  14.   
  15.     public static void main(String[] args) {  
  16.         InnerClass_NoName icn = new InnerClass_NoName();  
  17.         A a = icn.test();  
  18.         a.a();  
  19.     }  
  20. }  

典型的狀況是,內部類繼承自某個類或實現某個接口,內部類的代碼操做建立其的外圍類的對象。因此你能夠認爲內部類提供了某種進入其外圍類的窗口。使用內部類最吸引人的緣由是:每一個內部類都能獨立地繼承自一個(接口的)實現,因此不管外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。若是沒有內部類提供的能夠繼承多個具體的或抽象的類的能力,一些設計與編程問題就很難解決。從這個角度看,內部類使得多重繼承的解決方案變得完整。接口解決了部分問題,而內部類有效地實現了「多重繼承」。通常狀況,內部類不宜過長,不然就會顯得頭重腳輕。

使用匿名內部類應該注意:

a)        匿名內部類不能有構造方法

b)        匿名內部類不能定義任何靜態成員、方法和類。

c)         匿名內部類不能是public,protected,private,static。

d)        只能建立匿名內部類的一個實例。

e)        一個匿名內部類必定是在new的後面,用其隱含實現一個接口或實現一個類。

f)         因匿名內部類爲局部內部類,因此局部內部類的全部限制都對其生效。

嵌套類:

普通的內部類持有外圍類的一個引用,因此能夠與外部類保持聯繫,而當咱們須要嵌套類的時候,咱們須要使用static關鍵字,這樣內部類就斷開了和外部類的聯繫,不能從內部類的對象中訪問非靜態的外部類。

 

  1. public class InnerClass {  
  2.       
  3.     static class A{  
  4.         static int a = 10;  
  5.         static void a(){  
  6.             System.out.println("this is A.a()!");  
  7.         }  
  8.     }  
  9. }  

 

 

接口內部的類:

 

  1. public interface Interface_Class {  
  2.     void say();  
  3.     class IC implements Interface_Class{  
  4.         @Override  
  5.         public void say() {  
  6.             System.out.println("hello");  
  7.         }  
  8.         public static void main(String[] args) {  
  9.             new IC().say();  
  10.         }  
  11.     }  
  12. }  

適合於建立公共代碼,供全部實現了該接口的類使用。

內部類的繼承,咱們說過,內部類持有對外部類的引用,因此,在繼承的時候,咱們須要初始化這個「隱藏」着的引用,請看下面的代碼:

 

  1. class AAA {  
  2.     class BBB {  
  3.   
  4.     }  
  5. }  
  6.   
  7. public class InnerClass_Extends extends AAA.BBB {  
  8.     public InnerClass_Extends(AAA aaa) {  
  9.         aaa.super();  
  10.     }  
  11.   
  12.     public static void main(String[] args) {  
  13.         AAA aaa = new AAA();  
  14.         InnerClass_Extends ice = new InnerClass_Extends(aaa);  
  15.     }  
  16. }  

最後,咱們總結下使用內部類的緣由:每一個內部類都能獨立繼承自一個接口的實現,和外部類沒有任何關係(不論外部類是否實現了該接口)。

說的再簡單一點就是,內部類是Java多繼承機制的完美補充,爲何這樣說?咱們說過,實現多繼承靠的是接口,光從類的角度說是沒有多繼承一說的。可是,若是如今非得用抽象類實現多繼承,很明顯是不可能的,此處就必須使用內部類。舉個例子:

 

  1. class AA{  
  2.       
  3. }  
  4. abstract class BB{  
  5.       
  6. }  
  7. class CC extends AA{  
  8.     BB makeB(){  
  9.         return new BB(){  
  10.               
  11.         };  
  12.     }  
  13. }  
  14. public class Multi_Extends {  
  15.       
  16.     static void takesA(AA a){}  
  17.     static void takesB(BB b){}  
  18.       
  19.     public static void main(String[] args) {  
  20.         CC c = new CC();  
  21.         takesA(c);  
  22.         takesB(c.makeB());  
  23.     }  
  24.   
  25. }  

這樣就實現了繼承內部類。

相關文章
相關標籤/搜索