Java深入數據結構理解掌握抽象類與接口

abstract

abstract介紹:可以用於修飾:類(抽象類)、方法(抽象方法)

abstract修飾類:

①此類不能實例化(也就是不能創建這個類的對象)

②雖然自己不能實例化,但是子類會調用父類的構造器,所以抽象類中一定有構造器

abstract修飾方法

①抽象方法隻有方法的聲明沒有方法體,所在的類一定是抽象類。因為如果類不是抽象的,那這個類就可以造對象,可以造對象就可以調用。反之抽象類中可以沒有抽象方法。

② 若子類重寫瞭子類重寫瞭父類所有的抽象方法才能實例化,如果沒有全部重寫,那麼子類也是抽象類,也需要用abstract修飾。

③abstract不能用來修飾私有方法、靜態方法、final關鍵字修飾的方法、final關鍵字修飾的類。

final明確不能繼承,但abstract需要子類繼承所以不能用,因為如果兩個方法都是static,不認為兩個方法是重寫或者覆蓋,所以abstract用來修飾靜態方法,就無法重寫。

抽象的應用

模板方法設計模式。在軟件開發中實現一個算法時,整體步驟很固定、通用,這些步驟在父類中寫好,某些易變的和不確定的部分可以抽象出來給子類實現。

抽象類的匿名子類對象

public static void main(String[] args){
    //匿名對象
    eat(new son());
    //非匿名類的非匿名對象
    son John=new son();
    eat(John);
    //匿名子類對象
    father f=new father(){//抽象類造對象必須要重寫方法,瞭解看得懂就ok瞭。
        @Override
        public void work() {
        }
        @Override
        public void info(father i) {
        }
    };
}
//普通方法
public static void eat(father f){
    System.out.println("吃飯");
}
//父類
public abstract static class father{
    String name;
    int age;
    public abstract void work();//抽象方法不能有方法體
    public abstract void info(father i);
}
//子類
public class son extends father{//繼承
    String name;
    int age;
    @Override
    public void work(){
        System.out.println("上學");
    }
    @Override
    public void info(father i) {
        System.out.println("name:"+i.name+" age:"+i.age);
    }
}
//接口的匿名對象
非匿名的對象可以被多次調用,匿名的對象隻能使用一次
Computer com=new Computer();//創建瞭接口的非匿名實現類(子類)的非匿名對象,類和對象都是有名的
Flash flash = new Flash();
//2.創建瞭接口的非匿名實現類的匿名對象,對象匿名瞭
com.transferData(new Printer());
//3創建瞭接口的匿名實現類的非匿名對象,就是類是匿名的,就不知道是接口中的哪個實現類,所以 需要重寫方法進行說明
USB  phone = new USB{
    public void start(){
        ...
    }
};
//4.創建瞭接口的匿名實現類的匿名對象
com.transferData(new USB(){
    public void start(){
        ...
    }  
    });

final關鍵字

final修飾類:此類不能被其他類所繼承,比如:String、System、StringBuffer

final修飾方法:此方法不能再被重寫,比如:Object類中的getClass()

static final用來修飾屬性:全局常量

final修飾變量:此時的變量就稱為是一個常量

final修飾屬性:可以考慮賦值的位置:顯式初始化,代碼塊中初始化、構造器中初始化

final修飾局部變量:尤其是用final修飾形參時,表明此形參是一個常量,當調用此方法時,給常量形參賦實參,一旦賦值就隻能在方法體內使用此形參,但不能重新賦值

接口

接口使用Interface來定義,和類是並列關系

接口的定義以及接口中的成員:

接口相關規則

1.接口中所有方法都是抽象的。

2.即使沒有顯式的將接口中的成員用public標示,也是public訪問類型的

3.接口中變量默認用 public static final標示,所以接口中定義的變量就是全 局靜態常量。

4.可以定義一個新接口,用extends去繼承一個已有的接口

5.可以定義一個類,用implements去實現一個接口中所有方法。

6.可以定義一個抽象類,用implements去實現一個接口中部分方法。

接口的特性

1.接口不可以被實例化

2.實現類必須實現接口的所有方法

3.實現類可以實現多個接口

4.接口中的變量都是靜態常量

如果類覆蓋瞭接口中所有的抽象方法,則可以創造實例;如果類沒有覆蓋接口中所有的抽象方法,則該類仍為抽象類。Java類可以實現多個接口——彌補瞭單繼承性的缺陷

class AA extends BB implements CC,DD,EE

接口和接口之間可以繼承,且可以多繼承。接口的使用體現瞭多態性。接口是一種規范,面向接口編程。

抽象類和接口的異同

相同點:不能實例化,都可以包含抽象方法

不同點:

1. 把抽象類和接口(java7、java8)的定義、內部結構解釋說明

2. 類:單繼承性,接口:多繼承性。

抽象類與接口的練習

 abstract class Door {
    //開門
    public abstract void openDoor();
    //關門
    public abstract void closeDoor();
}
 interface Lock {
    public static final int num = 200;
    //開鎖
    public abstract void openLock();
    //上鎖
    public abstract void closeLock();
}
class LockDoor extends Door implements Lock {
    public void openDoor() {
        System.out.println("開門");
    }
    public void closeDoor() {
        System.out.println("關門");
    }
    public void openLock() {
        System.out.println("開鎖");
    }
    public void closeLock() {
        System.out.println("上鎖");
    }
  }
public class TestLockDoor {
    public static void main(String[] args) {
        LockDoor lockDoor = new LockDoor();
        lockDoor.openLock();
        lockDoor.openDoor();
        lockDoor.closeDoor();
        lockDoor.closeLock();
    }
} 

​ 接口的應用

兩種設計模式

– 代理模式

代理設計就是為其他對象提供一張代理以控制對這個對象的訪問

應用場景:安全代理、遠程代理、延遲加載

分類:靜態代理、動態代理

– 工廠模式

實現創建者和調用者的分離

interface A{
    int x=0;
}
class B{
    int x=1;
}
class C extends B implements A{
    public void pX(){
        System.out.println(x);
    }
    public static void main(String[] args){
        new C().pX();
    }
}
//問題:編譯期不知道是要輸出哪個x
System.out.println(super.x);//這個調用的是父類中的
System.out.println(A.x);//這個調用的是接口中的

java8中接口新特性

JDK8:除瞭全局常量和抽象方法,還可以定義靜態方法和默認方法(default關鍵字修飾)

public interface CompareA{  
  public static void method1(){
  //靜態方法        
  System.out.println("CompareA:北京");   
   }   
    public default void method2(){
    //默認方法        
    System.out.println("CompareA:上海");   
     }
  }

接口中定義的靜態方法隻能通過接口來調用,接口.方法。

通過實現類的對象,可以調用接口中的默認方法,對象.方法。

如果實現類重寫瞭接口中的默認方法,調用時仍然調用的是重寫以後的方法

如果子類(或實現類)繼承的父類和實現的接口中聲明瞭同名同參數的方法,子類在沒有重寫此方法的情況下調用的是父類中的方法——類優先原則

如果實現類實現瞭多個接口,而這個多個接口中定義瞭同名同參數的默認方法,在實現類沒有重寫方法的情況下會報”接口沖突“錯誤,此時需要重寫。

如何在子類(或者實現類)調用父類、接口中被重寫的方法? 接口.super.方法。

內部類

需要關註的問題:如何實例化成員內部類的對象:外部類Person,靜態內部類Brain,非靜態內部類Lungs,靜態成員內部類:new 外部類.內部類()

Person.Brain brain=new Person.Brain();

非靜態成員內部類:先造對象,對象.new 內部類()

Person p=new Person();
p.Lungs lungs=p.new Lungs();

如何在成員內部類中區分調用外部類的結構

形參直接調,所在類的用this.結構,外部類的用外部類.this.結構

成員內部類和局部內部類在編譯以後都會生成字節碼文件

成員內部類:外部類.內部類名.class

局部內部類:外部類.數字 內部類名.class

在局部內部類的方法中,如果調用局部內部類所在的方法中的局部變量,該局部變量必須用final關鍵字修飾(JAVA8之後可以不寫出來,但仍然還是final的)

public void Person(){
    int num=10;
    class AA{//局部內部類
        public void show(){//局部內部類的方法
            num=20;//試圖修改會報錯
            System.out.println(num);//調用局部內部類所在的方法中的局部變量
        }
    }
}

開發中局部內部類的使用

常用的局部內部類:

//方式一
public Comparable getCompareble(){
    class MyComparable implements Comparable{//局部內部類

        public int compareTo(Object o){
            return 0;
        }
    }
    return new MyComparable();
}
//方式二
public Comparable getCompareble(){
    return new Comparable(){

        public int CompareTo(Object o){
            return 0;
        }
    };
}

Java允許將一個類A聲明在另一個類B中,A為內部類,B為外部類

內部類的分類:成員內部類、局部內部類(方法內,代碼塊內,構造器內)

成員內部類

作為外部類的成員:可以調用外部類的結構,可以被static修飾

作為一個類:可以定義屬性、方法、構造器,可以用final、abstract修飾,可以被繼承

this.name//內部類的屬性

Person.this.name//外部類的屬性

總結

今天學習瞭抽象類,final關鍵字的使用,接口的概念,特點,以及使用方式,內部類。

到此這篇關於Java深入數據結構理解掌握抽象類與接口的文章就介紹到這瞭,更多相關Java抽象類與接口內容請搜索LevelAH以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持LevelAH!

推薦閱讀: