Java入門教程十(抽象類介面內部類匿名類)
抽象類(abstract)
一個類只定義了一個為所有子類共享的一般形式,至於細節則交給每一個子類去實現,這種類沒有任何具體的例項,只具有一些抽象的概念,那麼這樣的類稱為抽象類。
在面向物件領域,抽象類主要用來進行型別隱藏。比如,如果我們進行一個圖形編輯軟體的開發,就會發現問題領域存在著圓、三角形這樣一些具體概念,它們是不同的,但是它們都屬於形狀這樣一個概念,形狀這個概念在問題領域是不存在的,它就是一個抽象概念。正是因為抽象概念在問題領域沒有對應的具體概念,所以用以表徵抽象概念的抽象類是不能夠例項化的。
abstract class class_name { abstract type method_name(parameter); }
abstract 表示該類或該方法是抽象的;class_name 表示抽象類的名稱;method_name 表示抽象方法名稱,如果在一個方法之前使用 abstract 來修飾,則說明該方法是抽象方法,不能有方法體;parameter 表示方法引數列表。
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 }
介面
介面類似於類,但介面的成員沒有執行體,它只是方法、屬性、事件和索引符的組合而已。介面不能被例項化,介面沒有構造方法,沒有欄位。在應用程式中,介面就是一種規範,它封裝了可以被多個類繼承的公共部分。
介面繼承和實現繼承的規則不同,一個類只有一個直接父類,但可以實現多個介面。Java 介面本身沒有任何實現,只描述 public 行為,因此 Java 介面比 Java 抽象類更抽象化。Java 介面的方法只能是抽象的和公開的,Java 介面不能有構造方法,Java 介面可以有 public、Static 和 final 屬性。
介面把方法的特徵和方法的實現分隔開來,這種分隔體現在介面常常代表一個角色,它包裝與該角色相關的操作和屬性,而實現這個介面的類便是扮演這個角色的演員。一個角色由不同的演員來演,而不同的演員之間除了扮演一個共同的角色之外,並不要求其他的共同之處。
介面對於其宣告、變數和方法都做了許多限制,這些限制作為介面的特徵歸納如下:
具有 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();
}
}