Java深入數(shù)據(jù)結(jié)構(gòu)理解掌握抽象類與接口
abstract
abstract介紹:可以用于修飾:類(抽象類)、方法(抽象方法)
abstract修飾類:
①此類不能實例化(也就是不能創(chuàng)建這個類的對象)
②雖然自己不能實例化,但是子類會調(diào)用父類的構(gòu)造器,所以抽象類中一定有構(gòu)造器
abstract修飾方法
①抽象方法只有方法的聲明沒有方法體,所在的類一定是抽象類。因為如果類不是抽象的,那這個類就可以造對象,可以造對象就可以調(diào)用。反之抽象類中可以沒有抽象方法。
② 若子類重寫了子類重寫了父類所有的抽象方法才能實例化,如果沒有全部重寫,那么子類也是抽象類,也需要用abstract修飾。
③abstract不能用來修飾私有方法、靜態(tài)方法、final關(guān)鍵字修飾的方法、final關(guān)鍵字修飾的類。
final明確不能繼承,但abstract需要子類繼承所以不能用,因為如果兩個方法都是static,不認為兩個方法是重寫或者覆蓋,所以abstract用來修飾靜態(tài)方法,就無法重寫。
抽象的應(yīng)用
模板方法設(shè)計模式。在軟件開發(fā)中實現(xiàn)一個算法時,整體步驟很固定、通用,這些步驟在父類中寫好,某些易變的和不確定的部分可以抽象出來給子類實現(xiàn)。
抽象類的匿名子類對象
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("上學(xué)"); } @Override public void info(father i) { System.out.println("name:"+i.name+" age:"+i.age); } } //接口的匿名對象 非匿名的對象可以被多次調(diào)用,匿名的對象只能使用一次 Computer com=new Computer();//創(chuàng)建了接口的非匿名實現(xiàn)類(子類)的非匿名對象,類和對象都是有名的 Flash flash = new Flash(); //2.創(chuàng)建了接口的非匿名實現(xiàn)類的匿名對象,對象匿名了 com.transferData(new Printer()); //3創(chuàng)建了接口的匿名實現(xiàn)類的非匿名對象,就是類是匿名的,就不知道是接口中的哪個實現(xiàn)類,所以 需要重寫方法進行說明 USB phone = new USB{ public void start(){ ... } }; //4.創(chuàng)建了接口的匿名實現(xiàn)類的匿名對象 com.transferData(new USB(){ public void start(){ ... } });
final關(guān)鍵字
final修飾類:此類不能被其他類所繼承,比如:String、System、StringBuffer
final修飾方法:此方法不能再被重寫,比如:Object類中的getClass()
static final用來修飾屬性:全局常量
final修飾變量:此時的變量就稱為是一個常量
final修飾屬性:可以考慮賦值的位置:顯式初始化,代碼塊中初始化、構(gòu)造器中初始化
final修飾局部變量:尤其是用final修飾形參時,表明此形參是一個常量,當調(diào)用此方法時,給常量形參賦實參,一旦賦值就只能在方法體內(nèi)使用此形參,但不能重新賦值
接口
接口使用Interface來定義,和類是并列關(guān)系
接口的定義以及接口中的成員:
接口相關(guān)規(guī)則
1.接口中所有方法都是抽象的。
2.即使沒有顯式的將接口中的成員用public標示,也是public訪問類型的
3.接口中變量默認用 public static final標示,所以接口中定義的變量就是全 局靜態(tài)常量。
4.可以定義一個新接口,用extends去繼承一個已有的接口
5.可以定義一個類,用implements去實現(xiàn)一個接口中所有方法。
6.可以定義一個抽象類,用implements去實現(xiàn)一個接口中部分方法。
接口的特性
1.接口不可以被實例化
2.實現(xiàn)類必須實現(xiàn)接口的所有方法
3.實現(xiàn)類可以實現(xiàn)多個接口
4.接口中的變量都是靜態(tài)常量
如果類覆蓋了接口中所有的抽象方法,則可以創(chuàng)造實例;如果類沒有覆蓋接口中所有的抽象方法,則該類仍為抽象類。Java類可以實現(xiàn)多個接口——彌補了單繼承性的缺陷
class AA extends BB implements CC,DD,EE
接口和接口之間可以繼承,且可以多繼承。接口的使用體現(xiàn)了多態(tài)性。接口是一種規(guī)范,面向接口編程。
抽象類和接口的異同
相同點:不能實例化,都可以包含抽象方法
不同點:
1. 把抽象類和接口(java7、java8)的定義、內(nèi)部結(jié)構(gòu)解釋說明
2. 類:單繼承性,接口:多繼承性。
抽象類與接口的練習(xí)
abstract class Door { //開門 public abstract void openDoor(); //關(guān)門 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("關(guān)門"); } 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(); } }
? 接口的應(yīng)用
兩種設(shè)計模式
- 代理模式
代理設(shè)計就是為其他對象提供一張代理以控制對這個對象的訪問
應(yīng)用場景:安全代理、遠程代理、延遲加載
分類:靜態(tài)代理、動態(tài)代理
- 工廠模式
實現(xiàn)創(chuàng)建者和調(diào)用者的分離
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);//這個調(diào)用的是父類中的 System.out.println(A.x);//這個調(diào)用的是接口中的
java8中接口新特性
JDK8:除了全局常量和抽象方法,還可以定義靜態(tài)方法和默認方法(default關(guān)鍵字修飾)
public interface CompareA{ public static void method1(){ //靜態(tài)方法 System.out.println("CompareA:北京"); } public default void method2(){ //默認方法 System.out.println("CompareA:上海"); } }
接口中定義的靜態(tài)方法只能通過接口來調(diào)用,接口.方法。
通過實現(xiàn)類的對象,可以調(diào)用接口中的默認方法,對象.方法。
如果實現(xiàn)類重寫了接口中的默認方法,調(diào)用時仍然調(diào)用的是重寫以后的方法
如果子類(或?qū)崿F(xiàn)類)繼承的父類和實現(xiàn)的接口中聲明了同名同參數(shù)的方法,子類在沒有重寫此方法的情況下調(diào)用的是父類中的方法——類優(yōu)先原則
如果實現(xiàn)類實現(xiàn)了多個接口,而這個多個接口中定義了同名同參數(shù)的默認方法,在實現(xiàn)類沒有重寫方法的情況下會報”接口沖突“錯誤,此時需要重寫。
如何在子類(或者實現(xiàn)類)調(diào)用父類、接口中被重寫的方法? 接口.super.方法。
內(nèi)部類
需要關(guān)注的問題:如何實例化成員內(nèi)部類的對象:外部類Person,靜態(tài)內(nèi)部類Brain,非靜態(tài)內(nèi)部類Lungs,靜態(tài)成員內(nèi)部類:new 外部類.內(nèi)部類()
Person.Brain brain=new Person.Brain();
非靜態(tài)成員內(nèi)部類:先造對象,對象.new 內(nèi)部類()
Person p=new Person(); p.Lungs lungs=p.new Lungs();
如何在成員內(nèi)部類中區(qū)分調(diào)用外部類的結(jié)構(gòu)
形參直接調(diào),所在類的用this.結(jié)構(gòu),外部類的用外部類.this.結(jié)構(gòu)
成員內(nèi)部類和局部內(nèi)部類在編譯以后都會生成字節(jié)碼文件
成員內(nèi)部類:外部類.內(nèi)部類名.class
局部內(nèi)部類:外部類.數(shù)字 內(nèi)部類名.class
在局部內(nèi)部類的方法中,如果調(diào)用局部內(nèi)部類所在的方法中的局部變量,該局部變量必須用final關(guān)鍵字修飾(JAVA8之后可以不寫出來,但仍然還是final的)
public void Person(){ int num=10; class AA{//局部內(nèi)部類 public void show(){//局部內(nèi)部類的方法 num=20;//試圖修改會報錯 System.out.println(num);//調(diào)用局部內(nèi)部類所在的方法中的局部變量 } } }
開發(fā)中局部內(nèi)部類的使用
常用的局部內(nèi)部類:
//方式一 public Comparable getCompareble(){ class MyComparable implements Comparable{//局部內(nèi)部類 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為內(nèi)部類,B為外部類
內(nèi)部類的分類:成員內(nèi)部類、局部內(nèi)部類(方法內(nèi),代碼塊內(nèi),構(gòu)造器內(nèi))
成員內(nèi)部類
作為外部類的成員:可以調(diào)用外部類的結(jié)構(gòu),可以被static修飾
作為一個類:可以定義屬性、方法、構(gòu)造器,可以用final、abstract修飾,可以被繼承
this.name//內(nèi)部類的屬性
Person.this.name//外部類的屬性
總結(jié)
今天學(xué)習(xí)了抽象類,final關(guān)鍵字的使用,接口的概念,特點,以及使用方式,內(nèi)部類。
到此這篇關(guān)于Java深入數(shù)據(jù)結(jié)構(gòu)理解掌握抽象類與接口的文章就介紹到這了,更多相關(guān)Java抽象類與接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中IO流使用FileWriter寫數(shù)據(jù)基本操作詳解
這篇文章主要介紹了Java中IO流FileWriter寫數(shù)據(jù)操作,FileWriter類提供了多種寫入字符的方法,包括寫入單個字符、寫入字符數(shù)組和寫入字符串等,它還提供了一些其他的方法,如刷新緩沖區(qū)、關(guān)閉文件等,需要的朋友可以參考下2023-10-10springboot如何去獲取前端傳遞的參數(shù)的實現(xiàn)
這篇文章主要介紹了springboot如何去獲取前端傳遞的參數(shù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05使用Spring-Retry解決Spring Boot應(yīng)用程序中的重試問題
重試的使用場景比較多,比如調(diào)用遠程服務(wù)時,由于網(wǎng)絡(luò)或者服務(wù)端響應(yīng)慢導(dǎo)致調(diào)用超時,此時可以多重試幾次。用定時任務(wù)也可以實現(xiàn)重試的效果,但比較麻煩,用Spring Retry的話一個注解搞定所有,感興趣的可以了解一下2023-04-04Java BeanPostProcessor與BeanFactoryPostProcessor基礎(chǔ)使用講解
這篇文章主要介紹了Java BeanPostProcessor與BeanFactoryPostProcessor基礎(chǔ)使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-11-11