一個類只定義了一個爲全部子類共享的通常形式,至於細節則交給每個子類去實現,這種類沒有任何具體的實例,只具備一些抽象的概念,那麼這樣的類稱爲抽象類。ide
在面向對象領域,抽象類主要用來進行類型隱藏。好比,若是咱們進行一個圖形編輯軟件的開發,就會發現問題領域存在着圓、三角形這樣一些具體概念,它們是不一樣的,可是它們都屬於形狀這樣一個概念,形狀這個概念在問題領域是不存在的,它就是一個抽象概念。正是由於抽象概念在問題領域沒有對應的具體概念,因此用以表徵抽象概念的抽象類是不可以實例化的。模塊化
abstract class class_name { abstract type method_name(parameter); }
abstract 表示該類或該方法是抽象的;class_name 表示抽象類的名稱;method_name 表示抽象方法名稱,若是在一個方法以前使用 abstract 來修飾,則說明該方法是抽象方法,不能有方法體;parameter 表示方法參數列表。this
abstract 關鍵字只能用於普通方法,不能用於 static 方法或者構造方法中。在抽象類中必須包含至少一個抽象方法,而且全部抽象方法不能有具體的實現,而應在它們的子類中實現全部的抽象方法(要有方法體),包含一個或多個抽象方法的類必須經過在其 class 聲明前添加 abstract 關鍵字將其聲明爲抽象類。由於一個抽象類不定義完整的實現,因此抽象類也就沒有本身的對象。所以,任何使用 new 建立抽象類對象的嘗試都會致使編譯時錯誤。設計
public abstract class Shape { public int width; //幾何圖形的長 public int height; //幾何圖形的寬 public Shape(int width,int height) { this.width=width; this.height=height; } public abstract double area(); //定義抽象方法,計算面積 } public class Square extends Shape { public Square(int width,int height) { super(width,height); } @Override public double area()//重寫父類中的抽象方法,實現計算正方形面積的功能 { return width*height; } } public static void main(String[] args) { Square square=new Square(5,4); System.out.println("面積爲:"+square.area());//輸出:面積爲:20 }
接口相似於類,但接口的成員沒有執行體,它只是方法、屬性、事件和索引符的組合而已。接口不能被實例化,接口沒有構造方法,沒有字段。在應用程序中,接口就是一種規範,它封裝了能夠被多個類繼承的公共部分。code
接口繼承和實現繼承的規則不一樣,一個類只有一個直接父類,但能夠實現多個接口。Java 接口自己沒有任何實現,只描述 public 行爲,所以 Java 接口比 Java 抽象類更抽象化。Java 接口的方法只能是抽象的和公開的,Java 接口不能有構造方法,Java 接口能夠有 public、Static 和 final 屬性。對象
接口把方法的特徵和方法的實現分隔開來,這種分隔體如今接口經常表明一個角色,它包裝與該角色相關的操做和屬性,而實現這個接口的類即是扮演這個角色的演員。一個角色由不一樣的演員來演,而不一樣的演員之間除了扮演一個共同的角色以外,並不要求其餘的共同之處。blog
接口對於其聲明、變量和方法都作了許多限制,這些限制做爲接口的特徵概括以下:
具備 public 訪問控制符的接口,容許任何類使用;沒有指定 public 的接口,其訪問將侷限於所屬的包。
方法的聲明不須要其餘修飾符,在接口中聲明的方法,將隱式地聲明爲公有的(public)和抽象的(abstract)。
在 Java 接口中聲明的變量其實都是常量,接口中的變量聲明,將隱式地聲明爲 public、static 和 final,即常量,因此接口中定義的變量必須初始化。接口沒有構造方法,不能被實例化。繼承
public interface interfaceName{ } //例如 public interface Personlnterface{ String name; //不合法,變量name必須初始化 int age=20; //合法,等同於 public static final int age=20; void getInfo(); //方法聲明,等同於 public abstract void getInfo(); }
在實現類中,全部的方法都使用了 public 訪問修飾符聲明。不管什麼時候實現一個由接口定義的方法,它都必須實現爲 public,由於接口中的全部成員都顯式聲明爲 public索引
public class Person implements Personlnterface { public void getInfo(){ return "Hello World"; } }
public static void main(String[] args){ Personlnterface person = new Person(); person.getInfo();//返回 HelloWorld }
在面向對象的設計思想中,全部的對象都是經過類來描繪的,可是反過來,並非全部的類都是用來描繪對象的,若是一個類中沒有描繪一個具體的對象,那麼這樣的類就是抽象類,抽象類是對那些看上去不一樣,可是本質上相同的具體概念的抽象,正是由於抽象的概念在問題領域沒有對應的具體概念,因此抽象類是不可以實例化的接口
接口內只能是功能的定義,而抽象類中則能夠包括功能的定義和功能的實現。在接口中,全部的屬性確定是 public、static 和 final,全部的方法都是 abstract,因此能夠默認不寫上述標識符;在抽象類中,既能夠包含抽象的定義,也能夠包含具體的實現方法
public interface Animal { public void eat(); public String fly(); } public abstract class Animal { public abstract void eat(); public String fly(){ return "我會飛"; }; }
接口的實現類中使用 implements 關鍵字;而在抽象類的實現類中,則使用 extends 關鍵字。一個接口的實現類能夠實現多個接口,而一個抽象類的實現類則只能實現一個抽象類。
//接口 public class concreteAnimal implements Animal { public void eat(){} public void fly(){} } //抽象類 public class concreteAnimal extends Animal { public void eat(){} public void fly(){} }
從前面抽象類的具體實現類的實現方式能夠看出,其實在 Java 中,抽象類和具體實現類之間是一種繼承關係,也就是說若是釆用抽象類的方式,則父類和子類在概念上應該是相同的。接口卻不同,若是採用接口的方式,則父類和子類在概念上不要求相同。接口只是抽取相互之間沒有關係的類的共同特徵,而不用關注類之間的關係,它可使沒有層次關係的類具備相同的行爲。所以,能夠這樣說:抽象類是對一組具備相同屬性和方法的邏輯上有關係的事物的一種抽象,而接口則是對一組具備相同屬性和方法的邏輯上不相關的事物的一種抽象。
強列的is a 使用抽象類,has a 使用接口。如:鳥是一種動物。鳥有一個功能會飛。貓也是一種動物,可是貓不會飛。
//接口 public interface Fly { public void flyUp(); } //抽象類 public abstract class Animal { public abstract void eat(); } //貓是一種動物 public class Cat extends Animal{ } //鳥是一種動物,同時會飛 public class Bird extends Animal implements Run { }
抽象類是對一組具備相同屬性和方法的邏輯上有關係的事物的一種抽象,而接口則是對一組具備相同屬性和方法的邏輯上不相關的事物的一種抽象,所以抽象類表示的是「is a」關係,接口表示的是「has a」關係。
在一個類內部的類,咱們稱之爲內部類。內部類能夠很好地實現隱藏,通常的非內部類是不容許有 private 與 protected 權限的,但內部類能夠。內部類擁有外圍類的全部元素的訪問權限。
內部類能夠分爲:實例內部類、靜態內部類和成員內部類,每種內部類都有它特定的一些特色,本節先詳細介紹一些和內部類相關的知識。
內部類的特色以下:
內部類仍然是一個獨立的類,在編譯以後內部類會被編譯成獨立的 .class 文件,可是前面冠之外部類的類名和 $ 符號。
內部類不能用普通的方式訪問。內部類是外部類的一個成員,所以內部類能夠自由地訪問外部類的成員變量,不管是否爲 private 的。
內部類聲明成靜態的,就不能隨便訪問外部類的成員變量,仍然是隻能訪問外部類的靜態成員變量。
public class Test { public class InnerClass { public int getSum(int x,int y) { return x+y; } } public static void main(String[] args) { Test.InnerClass testInner =new Test().new InnerClass(); int i = testInner.getSum(2/3); System.out.println(i); //輸出5 } }
實例內部類是指沒有用 static 修飾的內部類
public class Outer { class Inner { //實例內部類 } }
在外部類的靜態方法和外部類之外的其餘類中,必須經過外部類的實例建立內部類的實例,若是有多層嵌套,則內部類能夠訪問全部外部類的成員
public class Outer { class Inner{} Inner i=new Inner(); //類內部不須要建立外部類實例 public void method0() { Inner j=new Inner(); //類內部不須要建立外部類實例 } public static void method1() { Inner r=new Outer().new inner(); //靜態方法須要建立外部類實例 } class Inner1 { Inner k=new Inner(); //不須要建立外部類實例 } } class OtherClass { Outer.Inner i=new Outer().new Inner(); //其餘類使用時須要建立外部類實例 }
靜態內部類是指使用 static 修飾的內部類
public class Outer { static class Inner { //靜態內部類 } }
在建立靜態內部類的實例時,不須要建立外部類的實例
public class Outer { static class Inner{} } class OtherClass { Outer.Inner oi=new Outer.Inner(); }
局部內部類是指在一個方法中定義的內部類
public class Test { public void method() { class Inner { //局部內部類 } } }
局部內部類與局部變量同樣,不能使用訪問控制修飾符(public、private 和 protected)和 static 修飾符修飾,局部內部類只在當前方法中有效,局部內部類中能夠訪問外部類的全部成員
public class Test { Inner i=new Inner(); //編譯出錯 Test.Inner ti=new Test.Inner(); //編譯出錯 Test.Inner ti2=new Test().new Inner(); //編譯出錯 public void method() { class Inner{} Inner i=new Inner(); } }
匿名類是指沒有類名的內部類,必須在建立時使用 new 語句來聲明類
new<類或接口>() { //類的主體 };
這種形式的 new 語句聲明一個新的匿名類,它對一個給定的類進行擴展,或者實現一個給定的接口。使用匿名類可以使代碼更加簡潔、緊湊,模塊化程度更高
匿名類有兩種實現方式:
繼承一個類,重寫其方法。
實現一個接口(能夠是多個),實現其方法。
public class Out { void show() { System.out.println("調用 Out 類的 show() 方法"); } } public class TestAnonymousInterClass { //在這個方法中構造一個匿名內部類 private void show() { Out anonyInter=new Out() { //獲取匿名內部類的實例 void show() { System.out.println("調用匿名類中的 show() 方法"); } }; anonyInter.show(); } public static void main(String[] args) { TestAnonymousInterClass test=new TestAnonymousInterClass(); test.show(); } }