[2014-3-11]JAVA筆記_抽象類(abstract class)、介面(interface)
一、 抽象類
抽象類(abstract class):使用abstract 關鍵字所修飾的類叫做抽象類。抽象類無法例項化,也就是說,不能 new 出來一個抽象類的物件(例項)。
抽象方法(abstract method):使用abstract 關鍵字所修飾的方法叫做抽象方法。抽象方法定義在抽象類中。抽象方法只有宣告,沒有實現,也就是說沒有{}。
·如果某個類是抽象類,那麼該類可以包含具體方法(有宣告、有實現)。
·如果一個類中包含了抽象方法,那麼這類一定要宣告成abstract class ,也就是說,該類一定是抽象類;反之,如果某個類是抽象類,那麼該類即可以包含抽象方法,也可以包含具體方法(全部是具體方法也可),也可以沒有方法。
·無論何種情況,只要一個類是抽象類,那麼這個類就無法例項化。
·在子類繼承父類(父類是個抽象類)的情況下,那麼該子類必須要實現父類中所定義的所有抽象方法;否則,該子類需要宣告成一個 abstract class。
注意:不能直接由抽象類建立物件,只能通過抽象類派生出新的類,再由它來建立物件。同樣存在單繼承的侷限,即一個子類只能繼承一個抽象類。
注意:·//繼承抽象類 abstract class A{ //包含抽象方法所以必須定義為抽象類 public static final String FLAG = "CHINA"; private String name = "Jerry"; public String getName(){ return name; } public void setName(String name){ this.name = name; } public abstract void print(); //定義抽象方法。只需要宣告,不需要實現。 } //抽象類必須被子繼承才可用抽象類 class B extends A{ //因為子類不是抽象類,所以必須覆寫抽象類中的全部抽象方法 public void print(){ System.out.println("FLAG = " + FLAG); System.out.println("姓名 = " + super.getName()); } } public class AbstractDemo02{ public static void main(String args[]){ B b = new B(); b.print(); } }
. 抽象類不能用final關鍵字定義。因為抽象類必須被繼承,而使用final關鍵字定義的類不能被繼承。
·. 抽象方法不要使用private宣告。因為抽象方法必須被子類覆寫,而如果使用private宣告則子類無法覆寫。
2. 抽象類中可以存在構造方法
總結:抽象類就是比普通類多定義了一個抽象方法,除了不能直接進行物件的例項化操作之外並沒有任何的不同。//呼叫抽象類中指定引數的構造方法 abstract class Person{ private String name; private int age; public Person(String name, int age){ this.setName(name); this.setAge(age); } public String getName(){ return name; } public void setName(String name){ this.name = name; } public int getAge(){ return age; } public void setAge(int age){ this.age = age; } public abstract String getInfo(); //取得資訊,抽象方法 } class Student extends Person{ private String school; public Student(String name, int age, String school){ super(name, age); this.setSchool(school); } public String getSchool(){ return school; } public void setSchool(String school){ this.school = school; } public String getInfo(){ //覆寫抽象類中的抽象方法 return "姓名:" + super.getName() + ";年齡:" + super.getAge() + ";學校:" + this.getSchool(); } } public class AbstractDemo03{ public static void main(String args[]){ Student stu = new Student("張三", 30, "清華大學"); System.out.println(stu.getInfo()); } }
二、介面
介面(Interface):介面的地位等同於class, 介面中的所有方法都是抽象方法。在宣告介面中的方法時,可以使用 abstract 關鍵字,也可以不用。通常情況會省略 abstract 關鍵字。
概念:可以將介面看作是特殊的抽象類(抽象類中可以有具體方法,也可以有抽象方法,而介面中只能有抽象方法,不能有具體方法)。介面是由全域性常量或公共的抽象方法所組成。
·類可以實現介面。實現使用關鍵字 implements 表示,代表了某個類實現了某個介面。
· 一個類實現了某個介面,那麼該類必須要實現介面中宣告的所有抽象方法。如果該類是抽象類,那麼就無需實現介面中的方法了(也可以實現,不過沒意義,因為抽象類不能被例項化)。
·Java 是單繼承的,也即是說某個類只能有唯一一個父類;一個類可以實現多個介面,多個介面之間使用逗號分隔。
·介面可以繼承介面(interface A extends B, C),介面不能實現介面(interface A implements B, C),類可以實現介面,但類不能繼承介面(class A extends B, C)。(例如類是具體要做什麼是實體的,而介面是抽象的、無實現的。所以抽象的可以繼承抽象的,抽象的不能實現抽象的,實體的可以實現抽象的,實體的不能繼承抽象的,因為實體的是告訴我們這個類具體是做什麼的,而不是告訴我們他是什麼)
·介面繼承介面後接口的方法也被繼承下來,可以通過子類實現子介面,子類重寫子介面方法和父介面方法。
why?:不允許類多重繼承的主要原因是,如果A同時繼承B和C,而b和c同時有一個D方法,A如何決定該繼承那一個呢?但介面不存在這樣的問題,介面全都是抽象方法繼承誰都無所謂,所以介面可以繼承多個介面。因為類如果可以多繼承,例項化時,如果要跳用父類的方法,如果兩個一樣,根本就不知道該呼叫那個父類的方法;但是介面就不一樣了,因為介面繼承多個介面,就算多個介面有相同的方法,但是最終實現介面的類只能實現一個方法且@Override一個方法,所以呼叫時就不會有問題了。
範例:介面中的方法必須全部實現。可以選擇由抽象類實現一部分,子類實現另一部分,或者其同包裡面的其他類實現。
package com.bob.test;
public class InterfaceTest {
public static void main(String[] args) {
C c = new C();
c.print1();
}
}
interface A{
public abstract void print1();
public abstract void print2();
public abstract void print3();
}
//抽象類可以選擇性實現抽象方法,但是未實現的抽象方法必須由子類實現,或者同包下的其它類檔案實現
abstract class B implements A{
public void print1(){
System.out.println("AAA");
}
}
另一個類檔案package com.bob.test;
public class AbstractMethodTest {
}
class C extends B{
public void print2(){
System.out.println("BBB");
}
public void print3(){
System.out.println("CCC");
}
}
[介面的定義格式]
interface 介面名稱{
全域性常量;
抽象方法;
}
注:java中介面的訪問許可權預設是public,不管寫與不寫,介面中的方法永遠是public。
//在介面中使用多型
public class Test4{
public static void main(String args[]){
AA aa = new BB(); //aa型別的引用指向bb型別的物件
aa.output();
//BB bb = (BB)aa; //向下型別轉換,與類轉換方法相同
}
}
interface AA{
public abstract void output();
}
class BB implements AA{
public void output(){
System.out.println("BB");
}
}
多型總結:所謂多型,就是父型別的引用可以指向子型別的物件,或者介面型別的引用可以指向實現該介面的類的例項。關於介面與實現介面的類之間的強制型別轉換方式與父類和子類之間的強制型別轉換方式完全一樣。
[格式 實現介面]
class 類 implements 介面A, 介面B,...{
}
//介面的實現
interface A{ //預設public許可權,可省略
public String AUTHOR = "Jerry"; //定義全域性常量,省略寫法
// public staitc final String AUTHOR = "Jerry"; //定義全域性常量,完整寫法
public void print(); //定義抽象方法,省略寫法
public abstract String getInfo(); //定義抽象方法,完整寫法
}
interface B{ //定義介面B
public abstract void say(); //定義抽象方法
}
class X implements A,B{ //子類同時實現兩個介面
public void say(){ //覆寫B介面中的抽象方法
System.out.println("Hello Interface");
}
public String getInfo(){ //覆寫A介面中的抽象方法
return "HELLO";
}
public void print(){ //覆寫A介面中的抽象方法
System.out.println("作者:" + AUTHOR);
}
}
public class InterfaceDemo03{
public static void main(String args[]){
X x = new X(); //例項化子類物件
x.say(); //呼叫被覆寫過的方法
x.print(); //呼叫被覆寫過的方法
}
}
子類既要實現介面又要繼承抽象類
//子類同時繼承抽象類和實現介面
interface A{ //預設public許可權,可省略
public String AUTHOR = "Jerry"; //定義全域性常量,省略寫法
// public staitc final String AUTHOR = "Jerry"; //定義全域性常量,完整寫法
public void print(); //定義抽象方法,省略寫法
public abstract String getInfo(); //定義抽象方法,完整寫法
}
abstract class B{ //定義抽象類B
public abstract void say(); //定義抽象方法
}
class X extends B implements A{ //子類同時實現介面
public void say(){ //覆寫B介面中的抽象方法
System.out.println("Hello Interface");
}
public String getInfo(){ //覆寫A介面中的抽象方法
return "HELLO";
}
public void print(){ //覆寫A介面中的抽象方法
System.out.println("作者:" + AUTHOR);
}
}
public class InterfaceDemo04{
public static void main(String args[]){
X x = new X(); //例項化子類物件
x.say(); //呼叫被覆寫過的方法
x.print(); //呼叫被覆寫過的方法
}
}
抽象類實現介面
//子類同時繼承抽象類和實現介面
interface A{ //預設public許可權,可省略
public String AUTHOR = "Jerry"; //定義全域性常量,省略寫法
// public staitc final String AUTHOR = "Jerry"; //定義全域性常量,完整寫法
public void print(); //定義抽象方法,省略寫法
public abstract String getInfo(); //定義抽象方法,完整寫法
}
abstract class B implements A{ //定義抽象類,實現介面
public abstract void say(); //此時抽象類中存在3個抽象方法
}
class X extends B { //子類繼承抽象類
public void say(){ //覆寫抽象B介面中的抽象方法
System.out.println("Hello Interface");
}
public String getInfo(){ //覆寫抽象類B中的抽象方法
return "HELLO";
}
public void print(){ //覆寫象類B中的抽象方法
System.out.println("作者:" + AUTHOR);
}
}
public class InterfaceDemo05{
public static void main(String args[]){
X x = new X(); //例項化子類物件
x.say(); //呼叫被覆寫過的方法
x.print(); //呼叫被覆寫過的方法
}
}
java中一個介面是不允許繼承抽象類的,但是允許一個介面繼承多個介面
[格式 介面的繼承]
interface 子介面 extends 父介面A, 父介面B,...{
}
//介面的多繼承
interface A{ //預設public許可權,可省略
public String AUTHOR = "Jerry"; //定義全域性常量,省略寫法
// public staitc final String AUTHOR = "Jerry"; //定義全域性常量,完整寫法
public abstract void printA(); //定義抽象方法,省略寫法
}
interface B{
public abstract void printB(); //定義抽象方法
}
interface C extends A,B{ //定義介面C, 同時繼承介面A、B
public abstract void printC();
}
class X implements C{ //子類實現介面C
public void printA(){
System.out.println("A、Hello World");
}
public void printB(){ //覆寫介面B中的printB()方法
System.out.println("B、Hello SDD");
}
public void printC(){
System.out.println("C、Hello DD"); //覆寫介面B中的printB()方法
}
}
public class InterfaceDemo06{
public static void main(String args[]){
X x = new X();
x.printA();
x.printB();
x.printB();
}
}//子介面繼承父介面,那麼實現子介面的時候必須覆寫子、父介面中所有的抽象方法
介面:由全域性常量和抽象方法組成,預設是public許可權,同抽象類相同也是由子類實現。因為介面中的方法預設是抽象方法,所以子類實現介面時必須覆寫所有介面中的方法。
抽象類:由abstract關鍵字定義的方法是抽象方法,包含一個抽象方法的類是抽象類,預設是public許可權。抽象方法只需要申明,不需要實現,也就是沒有{}主體內容。抽象類如果要使用必須由子類繼承,而且子類必須覆寫所有定義為abstract的抽象方法。
·如果一個抽象類實現了介面中一部分方法,另一個類繼承自抽象類,那麼子類必須實現抽象類中未實現的抽象方法
package com.bob.annotation;
public interface Usb {
public abstract void methoud1();
public abstract void methoud2();
public abstract void methoud3();
public abstract void methoud4();
}
//實現介面中的部分方法
abstract class Print implements Usb{
@Override
public void methoud1() {
System.out.println("implments method1.");
}
@Override
public void methoud2() {
System.out.println("implments method2.");
}
}
package com.bob.annotation;
//繼承抽象類Print
class Test extends Print {
public static void main(String[] args) {
Test test1 = new Test();
test1.methoud1();
}
//實現抽象類中未實現的方法
@Override
public void methoud3() {}
@Override
public void methoud4() {}
}
·如果一個抽象類實現了介面中的所有方法,方法體為空,那麼子類繼承抽象類可以選擇性的實現自己需要的方法。或者重寫父類中的方法package com.bob.annotation;
public interface Usb {
public abstract void methoud1();
public abstract void methoud2();
public abstract void methoud3();
public abstract void methoud4();
}
//實現介面全部方法
abstract class Print implements Usb{
@Override
public void methoud1() { //子類只想使用介面中的一個方法,可以用抽象類實現
System.out.println("implments method1.");
}
@Override
public void methoud2() {}
@Override
public void methoud3() {
// 空實現
}@Override
public void methoud4() {
// 空實現
}
}
package com.bob.annotation;
//繼承抽象類Print
class Test extends Print {
public static void main(String[] args) {
Test test1 = new Test();
test1.methoud1();
test1.methoud2();
}
@Override
public void methoud2() {
System.out.println("重寫父類的method2方法");
}
}
·抽象類肯定可以實現介面。這不是有沒有意義的事情,是一種思想,當你自己寫的類想用介面中個別方法的時候(注意不是所有的方法),那麼你就可以用一個抽象類先實現這個介面(方法體中為空),然後再用你的類繼承這個抽象類,這樣就可以達到你的目的了,如果你直接用類實現介面,那是所有方法都必須實現的;
·這種思想在java.swing.event包中運用的非常多,裡面一般以Adapter為字尾的都是抽象類,它們都實現了特定的事件介面,大家可以看看。