詳解JavaSE中抽象類與接口的定義及使用
一、抽象類
1、抽象類定義
1、什么是抽象類?
類和類之間具有共同特征,將這些共同特征提取出來,形成的就是抽象類。
類到對象是實(shí)例化,對象到類是抽象。

抽象類無法實(shí)例化,無法創(chuàng)建對象。抽象類是類和類之間有共同特征,將這些具有共同特征的類再進(jìn)一步抽象,就形成了抽象類。由于類本身是不存在的,所以抽象類無法創(chuàng)建對象,即無法實(shí)例化。
2、抽象類屬于什么類型?
抽象類也屬于引用數(shù)據(jù)類型。
3、抽象類的語法:
[修飾符列表] abstract class 類名{
類體;
}
4、抽象類是無法實(shí)例化的,無法創(chuàng)建對象,因此抽象類是用來被子類繼承的。
抽象類的子類還可以是抽象類
//銀行賬戶類
abstract class Account{
}
//信用卡類,子類繼承抽象類,子類可以實(shí)例化對象
class CreditAccount extends Account{
}
//抽象類的子類還可以是抽象類
abstract class Credit extends Account{
}
5、抽象類雖然無法實(shí)例化,但是抽象類有構(gòu)造方法,這個(gè)構(gòu)造方法是為子類提供的
2、抽象方法
抽象方法表示沒有實(shí)現(xiàn)的方法,沒有方法體的方法。
抽象方法的特點(diǎn):
1、沒有方法體,以分好結(jié)尾
2、前面修飾符列表當(dāng)中有abstract關(guān)鍵字
例如:
public abstract void doSome;
- 抽象類當(dāng)中不一定有抽象方法,但是有抽象方法的類一定是抽象類。
- 抽象類當(dāng)中可以有抽象方法也可以有非抽象方法。
- 抽象方法必須出現(xiàn)在抽象類當(dāng)中,一個(gè)非抽象類繼承抽象類,必須將抽象類當(dāng)中的抽象方法進(jìn)行實(shí)現(xiàn)。
abstract class Animal{
public abstract void move();
}
class Bird extends Animal{
//將抽象類當(dāng)中的抽象方法進(jìn)行重寫
public void move(){};
}
上面當(dāng)中,如果Bird類是抽象的話,則抽象方法也可以不重寫。
public class Test01 {
public static void main(String[] args) {
//使用多態(tài),父類型引用指向子類型對象
//Bird不是抽象類,可以創(chuàng)建對象,向上轉(zhuǎn)型
Animal a=new Bird();//面向抽象編程
a.move();
//在編譯的時(shí)候,a會(huì)檢查Animal當(dāng)中的move方法
//在執(zhí)行的時(shí)候,a會(huì)使用Bird當(dāng)中的move方法
}
}
判斷題:java語言當(dāng)中凡是沒有方法體的方法都是抽象方法(錯(cuò))
Object類當(dāng)中有很多方法都沒有方法體,都是以分好結(jié)尾的,但是他們都不是抽象方法,例如:
public native int hashCode();
這個(gè)方法底層調(diào)用了C++寫的動(dòng)態(tài)鏈接庫程序。前面修飾符列表中沒有abstract。有一個(gè)native,表示調(diào)用JVM本地的程序。
二、接口
1、接口定義
1、接口也是一種引用數(shù)據(jù)類型,編譯之后也是一個(gè)class字節(jié)碼文件。
2、接口是完全抽象的。(抽象類是半抽象的)或者說接口是特殊的抽象類。
3、接口的定義:
[修飾符列表] interface 接口名{
}
4、接口支持多繼承,一個(gè)接口可以繼承多個(gè)接口。
//定義接口
interface A{
}
interface B{
}
//支持多繼承
interface C extends A,B{
}
5、接口當(dāng)中只包含兩部分內(nèi)容,一部分是:常量,一部分是:抽象方法。
//我的數(shù)學(xué)接口
interface MyMath{
public abstract int sum(int a,int b);
}
6、接口當(dāng)中所有的元素都是public修飾的。
7、接口當(dāng)中的抽象方法定義時(shí):public abstract修飾符可以省略。
8、接口當(dāng)中的方法都是抽象方法,所有接口當(dāng)中的方法不能有方法體。
9、接口當(dāng)中的方法不能有大括號(hào),因?yàn)榇罄ㄌ?hào)就是方法體,而抽象方法不能有方法體。
10、接口當(dāng)中常量的修飾符:public static final可以省略。
11、常量不能重新賦值。
interface MyMath{
double PI=3.1415926;
//PI是常量
int sub(int a,int b);//相減的抽象方法
int sum(int a,int b);//相加的抽象方法
}
2、類實(shí)現(xiàn)接口
接口的基礎(chǔ)語法:
1、類和類之間叫做繼承,類和接口之間叫做實(shí)現(xiàn)。(其實(shí)仍然可以將實(shí)現(xiàn)看成是繼承)
- 繼承使用extends關(guān)鍵字完成
- 實(shí)現(xiàn)使用implements完成
- 當(dāng)一個(gè)非抽象類實(shí)現(xiàn)接口的話,必須將接口當(dāng)中所有的抽象方法全部實(shí)現(xiàn)。
interface MyMath{
double PI=3.1415926;
//PI是常量
int sub(int a,int b);//相減的抽象方法
int sum(int a,int b);//相加的抽象方法
}
class My implements MyMath{
public int sub(int x,int y){
return x-y;
}
public int sum(int x,int y){
return x+y;
}
}
接口和接口之間支持多繼承,一個(gè)類也可以同時(shí)實(shí)現(xiàn)多個(gè)接口。
這種機(jī)制彌補(bǔ)了java當(dāng)中類與類之間只支持單繼承的缺陷。
經(jīng)過測試,接口和接口之間在進(jìn)行強(qiáng)制類型轉(zhuǎn)換的時(shí)候,沒有繼承關(guān)系,也可以強(qiáng)轉(zhuǎn)。但是注意:在運(yùn)行時(shí)可能會(huì)出現(xiàn)ClassCastException異常。
public class Test04 {
public static void main(String[] args) {
M m=new E();
K k=(K)m;
}
}
interface K{
}
interface M{
}
class E implements M{
}

最終實(shí)際上和之前一樣,需要加instanceof運(yùn)算符進(jìn)行判斷。
這句話不適合在接口當(dāng)中:無論向上轉(zhuǎn)型還是向下轉(zhuǎn)型,兩種類型之間必須要有繼承關(guān)系,沒有繼承關(guān)系,則編譯器會(huì)報(bào)錯(cuò)。
上面的代碼更改如下:
if(m instanceof K){
K k=(K)m; //判斷,否則會(huì)出現(xiàn)異常
}
3、接口與多態(tài)聯(lián)合
public class Test02 {
public static void main(String[] args) {
MyMath m=new My();
//面向接口編程(調(diào)用接口里面的方法
int result=m.sub(10,20);
System.out.println(result);
int result2=m.sum(1,3);
System.out.println(result2);
}
}
//我的數(shù)學(xué)接口
interface MyMath{
double PI=3.1415926;
//PI是常量
int sub(int a,int b);//相減的抽象方法
int sum(int a,int b);//相加的抽象方法
}
class My implements MyMath{
public int sub(int x,int y){
return x-y;
}
public int sum(int x,int y){
return x+y;
}
}
4、extends和implements
問題:繼承和實(shí)現(xiàn)都存在的話,代碼應(yīng)該怎么寫?
如果同時(shí)出現(xiàn)繼承和實(shí)現(xiàn)的話,繼承的關(guān)鍵字在前面,實(shí)現(xiàn)的關(guān)鍵字在后面。
接口通常提取的是行為動(dòng)作。
class Cat extends Animal1 implements Flyable{
}
public class Test04 {
public static void main(String[] args) {
Flyable f=new Cat();//多態(tài)
f.fly();
Flyable f1=new Pig();
f1.fly();
}
}
//動(dòng)物類:父類
class Animal1{
}
//可飛翔的接口
interface Flyable{
void fly();
}
//動(dòng)物類子類:貓類
//flybale是一個(gè)接口,即一對翅膀,通過接口插到貓身上,讓貓可以飛翔
class Cat extends Animal1 implements Flyable{
public void fly(){
System.out.println("貓貓起飛!");
}
}
//動(dòng)物類子類:蛇類
//如果不想讓蛇飛,就不實(shí)現(xiàn)flyable接口
//沒有實(shí)現(xiàn)這個(gè)接口就表示沒有翅膀,那肯定不能飛翔
class Snack extends Animal1{
}
//動(dòng)物類子類:豬類,想讓豬飛,插接口
class Pig extends Animal1 implements Flyable{
public void fly(){
System.out.println("豬豬起飛!");
}
}

5、接口在開發(fā)當(dāng)中的作用
接口在開發(fā)當(dāng)中的作用,類似于多態(tài)在開發(fā)當(dāng)中的作用。
多態(tài):面向抽象編程,不面向具體編程,降低程序的耦合度,提高程序的擴(kuò)展力。
面向抽象編程可以修改為:面向接口編程。因?yàn)橛辛私涌诰陀辛丝刹灏巍?刹灏伪硎緮U(kuò)展能力強(qiáng),不是焊接死的。例如:主板和內(nèi)存條之間有插槽,這個(gè)插槽就是接口,內(nèi)存條壞了,可以重新買一個(gè)換,這就是高擴(kuò)展性和低耦合度。
實(shí)現(xiàn)一個(gè)菜單接口:
- 中午去飯館吃飯,這個(gè)過程當(dāng)中有接口,接口是抽象的。
- 菜單是一個(gè)接口。(菜單上面有一個(gè)抽象的照片:西紅柿炒雞蛋)
- 顧客面向菜單點(diǎn)菜,調(diào)用接口。
- 后臺(tái)的初始負(fù)責(zé)把西紅柿雞蛋做好,是接口的實(shí)現(xiàn)者。
- 這個(gè)菜單接口的作用:讓顧客和廚師解耦合,顧客不用找后廚,后廚不用找顧客,他們之間完全依靠這個(gè)抽象的菜單進(jìn)行溝通。符合OCP開發(fā)原則。
顧客有一個(gè)菜單 Customer has a FoodMenu,凡是能夠使用has a 來描述的,統(tǒng)一以屬性的方式存在
Cat is a Animal 凡是滿足 is a 的表示都可以設(shè)置為繼承。
西餐廚師類:
//西餐廚師實(shí)現(xiàn)菜單上面的菜
public class AmericanCooker implements FoodMenu{
public void xiHongShiJidan(){
System.out.println("西餐中的西紅柿炒雞蛋");
}
public void yuXiangRouSi(){
System.out.println("西餐中的魚香肉絲");
}
}
中餐廚師類:
//中餐廚師實(shí)現(xiàn)菜單上面的菜。廚師是接口的實(shí)現(xiàn)者。
public class ChinaCooker implements FoodMenu{
public void xiHongShiJidan(){
System.out.println("中餐中的西紅柿炒雞蛋");
}
public void yuXiangRouSi(){
System.out.println("中餐中的魚香肉絲");
}
}
顧客類:
public class Customer{
//面向接口編程
private FoodMenu foodmenu;//私有化體現(xiàn)封裝性,則要提供set和get方法
public Customer() {
}
public Customer(FoodMenu foodmenu) {
this.foodmenu = foodmenu;
}
public FoodMenu getFoodmenu() {
return foodmenu;
}
public void setFoodmenu(FoodMenu foodmenu) {
this.foodmenu = foodmenu;
}
public void order(){
//方法一:使用get方法拿到菜單
FoodMenu f=this.getFoodmenu();
//方法二:直接使用foodmenu,因?yàn)樗接械膶傩钥梢栽诒绢惍?dāng)中使用
foodmenu.xiHongShiJidan();
foodmenu.yuXiangRouSi();
}
}
菜單類:
public interface FoodMenu {
void xiHongShiJidan();
void yuXiangRouSi();
}
測試類:
public class Test {
public static void main(String[] args) {
//創(chuàng)建廚師對象(多態(tài))
FoodMenu menu1=new ChinaCooker();
FoodMenu menu2=new AmericanCooker();
//創(chuàng)建顧客對象
Customer m1=new Customer(menu1);
Customer m2=new Customer(menu2);
//顧客點(diǎn)菜
m1.order();
m2.order();
??????? }
}
任何一個(gè)接口都有調(diào)用者和實(shí)現(xiàn)者,接口可以將調(diào)用者和實(shí)現(xiàn)者解耦合。以后的大項(xiàng)目開發(fā),一般都是將項(xiàng)目分離成一個(gè)一個(gè)的模塊,模塊之間采用接口銜接,降低耦合度。
6、is has like
1.is a :Cat is an Animal.(貓是一個(gè)動(dòng)物)
凡是滿足is a的就表示繼承關(guān)系。
2.has a:He has a pen.(他有一只筆)
- 凡是能夠滿足has a 關(guān)系的表示關(guān)聯(lián)關(guān)系。
- 關(guān)聯(lián)關(guān)系通常以“屬性”的形式存在。
3.like a :Cooker like a menu.(廚師就像一個(gè)菜單)
- 凡是滿足like a 關(guān)系的表示實(shí)現(xiàn)關(guān)系。
- 實(shí)現(xiàn)關(guān)系通常是類實(shí)現(xiàn)接口。
7、抽象類與接口
抽象類與接口的區(qū)別:
- 抽象類是半抽象的,接口是完全抽象的。
- 抽象類中有構(gòu)造方法,接口當(dāng)中沒有構(gòu)造方法。
- 接口和接口之間支持多繼承,類和類之間只支持單繼承。
- 一個(gè)類可以同時(shí)實(shí)現(xiàn)多個(gè)接口,一個(gè)抽象類只能繼承一個(gè)類(單繼承)。
- 接口都在只允許出現(xiàn)常量和抽象方法。
到此這篇關(guān)于詳解JavaSE中抽象類與接口的定義及使用的文章就介紹到這了,更多相關(guān)JavaSE抽象類 接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java mybatis框架實(shí)現(xiàn)多表關(guān)系查詢功能
這篇文章主要介紹了java mybatis框架實(shí)現(xiàn)多表關(guān)系查詢,基于Maven框架的整體設(shè)計(jì) —— 一多一的關(guān)系,文中通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10
mybatis-parameterType傳入map條件方式
這篇文章主要介紹了mybatis-parameterType傳入map條件方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
SpringBoot+Mybatis+Vue 實(shí)現(xiàn)商品模塊的crud操作
這篇文章主要介紹了SpringBoot+Mybatis+Vue 實(shí)現(xiàn)商品模塊的crud操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Java Spring的數(shù)據(jù)庫開發(fā)詳解
這篇文章主要介紹了Spring的數(shù)據(jù)庫開發(fā),主要圍繞SpringJDBC和Spring Jdbc Template兩個(gè)技術(shù)來講解,文中有詳細(xì)的代碼示例,需要的小伙伴可以參考一下2023-04-04
Springboot中靜態(tài)文件的兩種引入方式總結(jié)
這篇文章主要介紹了Springboot中靜態(tài)文件的兩種引入方式總結(jié),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Spring注解@Value在controller無法獲取到值的解決
這篇文章主要介紹了Spring注解@Value在controller無法獲取到值的解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Java8的DateTimeFormatter與SimpleDateFormat的區(qū)別詳解
這篇文章主要介紹了Java8的DateTimeFormatter與SimpleDateFormat的區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
簡單談?wù)刯ava的異常處理(Try Catch Finally)
在程序設(shè)計(jì)中,進(jìn)行異常處理是非常關(guān)鍵和重要的一部分。一個(gè)程序的異常處理框架的好壞直接影響到整個(gè)項(xiàng)目的代碼質(zhì)量以及后期維護(hù)成本和難度。2016-03-03

