Java抽象類(lèi)與接口超詳細(xì)圖文解析
前言
在Java面向?qū)ο缶幊讨?,抽象?lèi)和接口是兩個(gè)非常重要的概念,它們?yōu)榇a的抽象化、模塊化和可擴(kuò)展性提供了強(qiáng)大的支持。無(wú)論是開(kāi)發(fā)大型企業(yè)級(jí)應(yīng)用,還是小型程序,掌握抽象類(lèi)和接口的使用都至關(guān)重要。本文將通過(guò)詳細(xì)的理論講解、豐富的代碼示例、直觀的圖片以及對(duì)比表格,幫助你深入理解Java抽象類(lèi)和接口的本質(zhì)與應(yīng)用。
一、抽象類(lèi)
1.什么是抽象類(lèi)
在面對(duì)對(duì)象的概念中,所以對(duì)象都是通過(guò)類(lèi)來(lái)描述的,但并不是所有的類(lèi)都是用來(lái)描述對(duì)象的,如果一個(gè)類(lèi)中沒(méi)有包含足夠的信息來(lái)描述一個(gè)具體的對(duì)象,這樣的類(lèi)就是抽象類(lèi)

Dog類(lèi)和Cat類(lèi)都屬于Animal類(lèi),但Dog()和Cat()方法沒(méi)有實(shí)際的行為,可以將他們?cè)O(shè)計(jì)成
抽象方法,包含抽象方法的類(lèi)就是抽象類(lèi)。
2.抽象類(lèi)語(yǔ)法
在Java中,被abstract修飾的類(lèi)稱(chēng)抽象類(lèi),抽象類(lèi)中,被abstract修飾的方法稱(chēng)為抽象方法,抽象方法不用給出具體的實(shí)現(xiàn)體。
public abstract class Animal {
abstract public void eat();//抽象方法:被abstract修飾,沒(méi)有方法體
public double show(){ //自己增加的方法
return show1;
}
protected double show1;//參數(shù)
}
3.抽象類(lèi)特征
3.1 抽象類(lèi)不能實(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)槌橄蠓椒ㄒ蛔宇?lèi)重寫(xiě)
abstract final void eat(); abstract public static void eat();

3.4 抽象類(lèi)必須被繼承,并且繼承后子類(lèi)要重寫(xiě)父類(lèi)的抽象方法,除非子類(lèi)也是抽象類(lèi),用abstract修飾
public abstract class Cat extends Animal {
@Override
public void eat(){
}
}
public abstract class Cat extends Animal {
@Override
public abstract void eat();
}
3.5 抽象類(lèi)中不?定包含抽象?法,但是有抽象?法的類(lèi)?定是抽象類(lèi)
3.6 抽象類(lèi)中可以有構(gòu)造?法,供?類(lèi)創(chuàng)建對(duì)象時(shí),初始化?類(lèi)的成員變量
4.抽象類(lèi)的作用
抽象類(lèi)本身不能被實(shí)例化,只能創(chuàng)建子類(lèi),并且重寫(xiě)抽象方法,這就起到檢驗(yàn)的作用
二、接口
1.什么是接口?
字面意思:我們生活中的水龍頭,插座,充電線都是有接口的,才能插上。
接口就是公共的行為規(guī)范標(biāo)準(zhǔn),在實(shí)現(xiàn)時(shí),只要符合規(guī)范標(biāo)準(zhǔn),就能通用
2.語(yǔ)法規(guī)則
接口的定義和類(lèi)基本相同,將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
}
【注意】
- 接口命名一般以大寫(xiě)字母
I開(kāi)頭;- 接口不能被實(shí)例化;
3.接口的使用
類(lèi)與接口之間是implements的關(guān)系
public class 類(lèi)名 implenments 接口名{
//...
}
這里建立一個(gè)IUSB接口和Mouse類(lèi)
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 接口是一種引用類(lèi)型,但是不能直接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)來(lái)實(shí)現(xiàn)
public interface USB {
//void openDevice();
void closeDevice(){
System.out.println("關(guān)閉USB設(shè)備");
}
}

4.4 重寫(xiě)接口方法時(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è)類(lèi)可以實(shí)現(xiàn)多個(gè)接口,這就是繼承所做不到的
- 這里創(chuàng)建一個(gè)
Dog類(lèi),可以讓他實(shí)現(xiàn)多個(gè)接口,如IRunning,ISwimming,IFlying。每個(gè)接口的抽象方法都有重寫(xiě),否則必須設(shè)置為抽象類(lèi)AIT + InS快捷鍵重寫(xiě)
public class Dog extends Animal implements IRunning,ISwimming{
@Override
public void run() {
}
@Override
public void swim() {
}
}
狗:既能跑,又能游;
【注意】
有了接口之后,我們就不用注意具體類(lèi)型,只需要關(guān)注這個(gè)類(lèi)是否具備某種類(lèi)型
6.接口間的繼承
在Java中,類(lèi)和類(lèi)之間是單繼承的,但一個(gè)類(lèi)可以實(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 類(lèi)中存在?個(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)制類(lèi)型轉(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.抽象類(lèi)和接口的區(qū)別
抽象類(lèi)中可以包含普通?法和普通字段,這樣的普通?法和字段可以被?類(lèi)直接使?(不必重寫(xiě)),
?接?中不能包含普通?法,?類(lèi)必須重寫(xiě)所有的抽象?法.
| No | 區(qū)別 | 抽象類(lèi)(abstract) | 接口(interface) |
|---|---|---|---|
| 1 | 結(jié)構(gòu)組成 | 普通類(lèi)+抽象方法 | 抽象方法+全局常量 |
| 2 | 權(quán)限 | 各種權(quán)限 | public |
| 3 | 子類(lèi)使用 | 使用extends關(guān)鍵字繼承抽象類(lèi) | 使用implements關(guān)鍵字實(shí)現(xiàn)接口 |
| 4 | 關(guān)系 | 一個(gè)抽象類(lèi)可以實(shí)現(xiàn)若干接口 | 接口不能繼承抽象類(lèi),可extends繼承多個(gè)父接口 |
| 5 | 子類(lèi)限制 | 一個(gè)子類(lèi)只能繼承一個(gè)抽象類(lèi) | 一個(gè)子類(lèi)可以實(shí)現(xiàn)多個(gè)接口 |
總結(jié)
在 Java 里,抽象類(lèi)與接口是實(shí)現(xiàn)抽象編程的關(guān)鍵工具。抽象類(lèi)融合普通類(lèi)與抽象方法,可定義部分實(shí)現(xiàn)邏輯,權(quán)限靈活;接口由抽象方法和全局常量構(gòu)成,成員權(quán)限默認(rèn) public 。子類(lèi)繼承抽象類(lèi)用 extends ,實(shí)現(xiàn)接口用 implements 。關(guān)系上,抽象類(lèi)能實(shí)現(xiàn)多個(gè)接口,接口可多繼承。繼承限制方面,子類(lèi)單繼承抽象類(lèi),卻可多實(shí)現(xiàn)接口 。二者各有適用場(chǎng)景,抽象類(lèi)適合提煉共性、留存部分實(shí)現(xiàn);接口利于規(guī)范行為、實(shí)現(xiàn)多態(tài)解耦。合理運(yùn)用它們,能讓代碼架構(gòu)更清晰、可擴(kuò)展與可維護(hù),助力構(gòu)建靈活且健壯的 Java 程序 。
到此這篇關(guān)于Java抽象類(lèi)與接口的文章就介紹到這了,更多相關(guān)Java抽象類(lèi)與接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java Spring 5 新特性函數(shù)式Web框架詳細(xì)介紹
正如昨天Juergen博客中所提到的,Spring 5.0的第二個(gè)里程碑是引入了一個(gè)新的函數(shù)式web框架。在這篇文章中,我們將給出關(guān)于這個(gè)框架的更多信息,,需要的朋友可以參考下2016-12-12
JAVA中出現(xiàn)異常、拋出異常后續(xù)代碼是否執(zhí)行情況詳析
當(dāng)產(chǎn)生異常后,并在異常處理器中進(jìn)行執(zhí)行之后,程序會(huì)是如何的一種狀態(tài),是終止還是繼續(xù)執(zhí)行處理之后的代碼呢,下面這篇文章主要給大家介紹了關(guān)于JAVA中出現(xiàn)異常、拋出異常后續(xù)代碼是否執(zhí)行情況的相關(guān)資料,需要的朋友可以參考下2024-05-05
Springboot視頻接口報(bào)大量的ClientAbortException找不到原因的解決
本文主要介紹了Springboot視頻接口報(bào)大量的ClientAbortException找不到原因的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08
JAVA雙親委派機(jī)制詳解及實(shí)際應(yīng)用場(chǎng)景
雙親委派機(jī)制是Java類(lèi)加載器加載類(lèi)時(shí)的一種策略,這篇文章主要介紹了JAVA雙親委派機(jī)制的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-08-08
微信公眾號(hào)獲取access_token的方法實(shí)例分析
這篇文章主要介紹了微信公眾號(hào)獲取access_token的方法,結(jié)合實(shí)例形式分析了java實(shí)現(xiàn)微信公眾號(hào)獲取access_token的相關(guān)原理、實(shí)現(xiàn)方法及操作注意事項(xiàng),需要的朋友可以參考下2019-10-10

