Java抽象類與接口超詳細(xì)圖文解析
前言
在Java面向?qū)ο缶幊讨?,抽象類和接口是兩個(gè)非常重要的概念,它們?yōu)榇a的抽象化、模塊化和可擴(kuò)展性提供了強(qiáng)大的支持。無(wú)論是開(kāi)發(fā)大型企業(yè)級(jí)應(yīng)用,還是小型程序,掌握抽象類和接口的使用都至關(guān)重要。本文將通過(guò)詳細(xì)的理論講解、豐富的代碼示例、直觀的圖片以及對(duì)比表格,幫助你深入理解Java抽象類和接口的本質(zhì)與應(yīng)用。
一、抽象類
1.什么是抽象類
在面對(duì)對(duì)象的概念中,所以對(duì)象都是通過(guò)類來(lái)描述的,但并不是所有的類都是用來(lái)描述對(duì)象的,如果一個(gè)類中沒(méi)有包含足夠的信息來(lái)描述一個(gè)具體的對(duì)象,這樣的類就是抽象類
Dog類和Cat類都屬于Animal類,但Dog()和Cat()方法沒(méi)有實(shí)際的行為,可以將他們?cè)O(shè)計(jì)成
抽象方法
,包含抽象方法的類就是抽象類
。
2.抽象類語(yǔ)法
在Java中,被abstract
修飾的類稱抽象類,抽象類中,被abstract
修飾的方法稱為抽象方法,抽象方法不用給出具體的實(shí)現(xiàn)體。
public abstract class Animal { abstract public void eat();//抽象方法:被abstract修飾,沒(méi)有方法體 public double show(){ //自己增加的方法 return show1; } protected double show1;//參數(shù) }
3.抽象類特征
3.1 抽象類不能實(shí)例化對(duì)象
public abstract class Animal { Animal animal = new Animal(); }
3.2 抽象方法不能是private的
public abstract class Animal { abstract private void eat();//抽象方法:被abstract修飾,沒(méi)有方法體 }
3.3 抽象方法不能被final和static修飾,因?yàn)槌橄蠓椒ㄒ蛔宇愔貙?/h4>
abstract final void eat();
abstract public static void eat();
abstract final void eat(); abstract public static void eat();
3.4 抽象類必須被繼承,并且繼承后子類要重寫父類的抽象方法,除非子類也是抽象類,用abstract修飾
public abstract class Cat extends Animal { @Override public void eat(){ } }
public abstract class Cat extends Animal { @Override public abstract void eat(); }
3.5 抽象類中不?定包含抽象?法,但是有抽象?法的類?定是抽象類
3.6 抽象類中可以有構(gòu)造?法,供?類創(chuàng)建對(duì)象時(shí),初始化?類的成員變量
4.抽象類的作用
抽象類本身不能被實(shí)例化,只能創(chuàng)建子類,并且重寫抽象方法,這就起到檢驗(yàn)的作用
二、接口
1.什么是接口?
字面意思:我們生活中的水龍頭,插座,充電線都是有接口的,才能插上。
接口
就是公共的行為規(guī)范標(biāo)準(zhǔn),在實(shí)現(xiàn)時(shí),只要符合規(guī)范標(biāo)準(zhǔn),就能通用
2.語(yǔ)法規(guī)則
接口的定義和類基本相同,將class
換成interface
關(guān)鍵字
public interface IShape { public static final int SIZE = 100;//接口變量默認(rèn)public static final public abstract void test();//接口方法默認(rèn)public abstract }
【注意】
- 接口命名一般以大寫字母
I
開(kāi)頭;- 接口不能被實(shí)例化;
3.接口的使用
類與接口之間是implements的關(guān)系
public class 類名 implenments 接口名{ //... }
這里建立一個(gè)IUSB接口和Mouse類
public interface IUSB { void openDevice(); void closeDevice(); }
public class Mouse implements IUSB{ @Override public void openDevice() { System.out.println("打開(kāi)鼠標(biāo)"); } @Override public void closeDevice() { System.out.println("關(guān)閉鼠標(biāo)"); } }
4.接口特性
4.1 接口是一種引用類型,但是不能直接new接口的對(duì)象
public class TestUSB { public static void main(String[] args) { USB usb = new USB(); } }
4.2 接口中的方法會(huì)被默認(rèn)為public abstract,其他修飾符會(huì)報(bào)錯(cuò)
public interface USB { private void openDevice();//private使用錯(cuò)誤 void closeDevice(); }
4.3 接口中的方法不能在接口中實(shí)現(xiàn),只能通過(guò)接口的類來(lái)實(shí)現(xiàn)
public interface USB { //void openDevice(); void closeDevice(){ System.out.println("關(guān)閉USB設(shè)備"); } }
4.4 重寫接口方法時(shí),不能使用默認(rèn)的訪問(wèn)權(quán)限
public class Mouse implements USB{ @Override public void openDevice() { System.out.println("打開(kāi)鼠標(biāo)"); } }
4.5 接口中可以有變量,但他會(huì)被默認(rèn)為public static final 變量
public interface USB { int susu = 250;//默認(rèn)被final public static修飾 void openDevice(); void closeDevice(); }
4.6 接口中不能有靜態(tài)代碼塊和構(gòu)造方法
public interface USB { public USB(){ } { } int susu = 250;//默認(rèn)被final public static修飾 void openDevice(); void closeDevice(); }
5.實(shí)現(xiàn)多個(gè)接口
一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,這就是繼承所做不到的
- 這里創(chuàng)建一個(gè)
Dog類
,可以讓他實(shí)現(xiàn)多個(gè)接口
,如IRunning,ISwimming,IFlying。每個(gè)接口的抽象方法都有重寫,否則必須設(shè)置為抽象類AIT + InS
快捷鍵重寫
public class Dog extends Animal implements IRunning,ISwimming{ @Override public void run() { } @Override public void swim() { } }
狗:既能跑,又能游;
【注意】
有了接口之后,我們就不用注意具體類型,只需要關(guān)注這個(gè)類是否具備某種類型
6.接口間的繼承
在Java中,類和類之間是單繼承的,但一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,接口與接口之間可以多繼承
這段代碼就繼承了兩個(gè)接口:游和跑
public class Dog extends Animal implements ISwimming,IRunning{ @Override public void run() { } @Override public void swim() { } }
7.接口使用實(shí)例
對(duì)象之間大小比較:
public class Student { public String name; public int score; public Student (String name,int score){ this.name=name; this.score=score; } @Override public String toString() { return super.toString(); } }
public class Test { public static void main(String[] args) { Student s1 = new Student("小華",20); Student s2 = new Student("小張",10); System.out.println(s1>s2); } }
這樣進(jìn)行比較會(huì)報(bào)錯(cuò),因?yàn)闆](méi)有指定根據(jù)分?jǐn)?shù)還是什么來(lái)比較,這樣不太靈活,我們可以使用接口,如下:
使用Comparable接口
public class Student implements Comparable<Student>{ public String name; public int age; public Student (String name,int age){ this.name=name; this.age=age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int compareTo(Student o) { if(this.age>o.age) return 1; else if(this.age == o.age) return 0; else return -1; } }
public class Test { public static void main(String[] args) { Student s1 = new Student("小華",20); Student s2 = new Student("小張",12); //System.out.println(s1>s2); if(s1.compareTo(s2)>0){ System.out.println("s1>s2"); } } }
使用Comparator接口
import java.util.Comparator; public class AgeComparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.age-o2.age; } }
public class Test { public static void main(String[] args) { Student s1 = new Student("小華",20); Student s2 = new Student("小張",12); AgeComparator ageComparator=new AgeComparator(); int ret = ageComparator.compare(s1,s2); if(ret>0){ System.out.println("s1>s2"); }
如果是根據(jù)名字來(lái)比較的,就要看對(duì)應(yīng)字母的大小
8.Clonable接口和深拷貝
8.1 Clonable接口
Java 中內(nèi)置了?些很有?的接?,Clonable
就是其中之?.Object 類
中存在?個(gè)clone?法
,調(diào)?這個(gè)?法可以創(chuàng)建?個(gè)對(duì)象的"拷?".但是要想合法調(diào)?clone
?法,必須要先實(shí)現(xiàn)Clonable接?,否則就會(huì)拋出CloneNotSupportedException
異常.
public class Person implements Cloneable{ public String name; public int age; public Person (String name,int age){ this.name=name; this.age=age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
public class Test1 { public static void main(String[] args) throws CloneNotSupportedException{ Person person1 = new Person("小華子",20); Person person2 = (Person) person1.clone();//強(qiáng)制類型轉(zhuǎn)換 System.out.println(person2); } }
受查異常/編譯時(shí)異常
解決方法:
8.2 淺拷貝
class Money implements Cloneable{ public double money = 9.9;
@Override protected Object clone() throws CloneNotSupportedException { return super.clone();
lic class Test1 { public static void main(String[] args) throws CloneNotSupportedException{ Person person1 = new Person("小華子",20); Person person2 = (Person) person1.clone(); System.out.println(person1.m.money); System.out.println(person2.m.money); System.out.println("=============="); person2.m.money = 19.9; System.out.println(person1.m.money); System.out.println(person2.m.money); }
通過(guò)clone,我們只是拷?了Person對(duì)象。但是Person對(duì)象中的Money對(duì)象,并沒(méi)有拷?。通過(guò)person2這個(gè)引?修改了m的值后,person1這個(gè)引?訪問(wèn)m的時(shí)候,值也發(fā)?了改變。這?就是發(fā)?了淺拷?。
8.3 深拷貝
class Money implements Cloneable{ public double money = 9.9; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } public class Person implements Cloneable{ public String name; public int age; public Money m = new Money(); public Person (String name,int age){ this.name=name; this.age=age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override protected Object clone() throws CloneNotSupportedException { //return super.clone(); Person tmp = (Person) super.clone(); tmp.m = (Money) this.m.clone(); return tmp; } }
public class Test1 { public static void main(String[] args) throws CloneNotSupportedException{ Person person1 = new Person("小華子",20); Person person2 = (Person) person1.clone(); System.out.println(person1.m.money); System.out.println(person2.m.money); System.out.println("=============="); person2.m.money = 19.9; System.out.println(person1.m.money); System.out.println(person2.m.money); }
核心代碼:
9.抽象類和接口的區(qū)別
抽象類中可以包含普通?法和普通字段,這樣的普通?法和字段可以被?類直接使?(不必重寫),
?接?中不能包含普通?法,?類必須重寫所有的抽象?法.
No | 區(qū)別 | 抽象類(abstract) | 接口(interface) |
---|---|---|---|
1 | 結(jié)構(gòu)組成 | 普通類+抽象方法 | 抽象方法+全局常量 |
2 | 權(quán)限 | 各種權(quán)限 | public |
3 | 子類使用 | 使用extends 關(guān)鍵字繼承抽象類 | 使用implements 關(guān)鍵字實(shí)現(xiàn)接口 |
4 | 關(guān)系 | 一個(gè)抽象類可以實(shí)現(xiàn)若干接口 | 接口不能繼承抽象類,可extends 繼承多個(gè)父接口 |
5 | 子類限制 | 一個(gè)子類只能繼承一個(gè)抽象類 | 一個(gè)子類可以實(shí)現(xiàn)多個(gè)接口 |
總結(jié)
在 Java 里,抽象類與接口是實(shí)現(xiàn)抽象編程的關(guān)鍵工具。抽象類融合普通類與抽象方法,可定義部分實(shí)現(xiàn)邏輯,權(quán)限靈活;接口由抽象方法和全局常量構(gòu)成,成員權(quán)限默認(rèn) public 。子類繼承抽象類用 extends ,實(shí)現(xiàn)接口用 implements 。關(guān)系上,抽象類能實(shí)現(xiàn)多個(gè)接口,接口可多繼承。繼承限制方面,子類單繼承抽象類,卻可多實(shí)現(xiàn)接口 。二者各有適用場(chǎng)景,抽象類適合提煉共性、留存部分實(shí)現(xiàn);接口利于規(guī)范行為、實(shí)現(xiàn)多態(tài)解耦。合理運(yùn)用它們,能讓代碼架構(gòu)更清晰、可擴(kuò)展與可維護(hù),助力構(gòu)建靈活且健壯的 Java 程序 。
到此這篇關(guān)于Java抽象類與接口的文章就介紹到這了,更多相關(guān)Java抽象類與接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Collections.shuffle()方法案例詳解
這篇文章主要介紹了Java Collections.shuffle()方法案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08javaweb圖書(shū)商城設(shè)計(jì)之訂單模塊(5)
這篇文章主要為大家詳細(xì)介紹了javaweb圖書(shū)商城設(shè)計(jì)之訂單模塊,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11springboot自定義配置及自定義對(duì)象映射的全流程
這篇文章主要介紹了springboot自定義配置及自定義對(duì)象映射的全流程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10三分鐘教你如何在IDEA中快速創(chuàng)建工程的方法
這篇文章主要介紹了三分鐘教你如何在IDEA中快速創(chuàng)建工程的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04詳解eclipse項(xiàng)目中的.classpath文件原理
這篇文章介紹了eclipse項(xiàng)目中的.classpath文件的原理,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12Java通過(guò)值查找對(duì)應(yīng)的枚舉的實(shí)現(xiàn)
本文主要介紹了Java通過(guò)值查找對(duì)應(yīng)的枚舉的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-02-02MySQL text類型對(duì)應(yīng)mybatis jdbcType類型方式
這篇文章主要介紹了MySQL text類型對(duì)應(yīng)mybatis jdbcType類型方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07