解析JavaSe的抽象類和接口
1. 抽象類和抽象方法
抽象方法和抽象類必須使用abstract修飾符來定義,有抽象方法的類只能被定義成抽象類,抽象類里可以沒有抽象方法。抽象方法和抽象類的規(guī)則如下:
(1) 抽象類和抽象方法必須使用abstract修飾符來修飾,抽象方法不能有方法體。
(2) 抽象類不能被實例化,無法使用new關(guān)鍵字來調(diào)用抽象類的構(gòu)造器創(chuàng)建抽象類的實例。即使抽象類里不包含抽象方法,這個抽象類也不能創(chuàng)建實例。
(3) 抽象類可以包含F(xiàn)ield、方法、構(gòu)造器、初始化塊、內(nèi)部類、枚舉類6種成分。抽象類的構(gòu)造器不能用于創(chuàng)建實例,主要是用于被其子類調(diào)用。
(4) 含有抽象方法的類只能被定義成抽象類。
(5) abstract不能用于修飾Field,不能用于修飾局部變量,即沒有抽象變量、沒有抽象Field等說法;abstract也不能用于修飾構(gòu)造器,沒有抽象構(gòu)造器,抽象類里定義的構(gòu)造器只能是普通構(gòu)造器。
定義抽象方法只需在普通方法上增加abstract修飾符,并把普通方法的方法體(也就是方法后花括號括起來的部分)全部去掉,并在方法后增加分號即可。
public abstract class Person {
// 初始化塊
{
System.out.println("執(zhí)行Person類的初始化塊");
}
private int age;
// 該構(gòu)造器并不是為了創(chuàng)建對象,而是為了子類調(diào)用
public Person(){
}
public Person(int age){
this.age = age;
}
// 抽象方法,沒有方法體
public abstract void show();
public void test(){
System.out.println("非抽象方法");
}
}
抽象類不能用于創(chuàng)建實例,只能當(dāng)作父類被其他子類繼承。
public class Student extends Person {
public Student(int age){
super(age);
}
@Override
public void show() {
System.out.println("重寫抽象類中的抽象方法");
}
}
注意:
(1) 當(dāng)使用abstract修飾類時,表明這個類只能被繼承;當(dāng)使用abstract修飾方法時,表明這個方法必須由子類提供實現(xiàn)(即重寫)。而final修飾的類不能被繼承,final修飾的方法不能被重寫。因此final和abstract永遠不能同時使用。
(2) 當(dāng)使用static修飾一個方法時,表明這個方法屬于該類本身,即通過類就可調(diào)用該方法,但如果該方法被定義成抽象方法,則將導(dǎo)致通過該類來調(diào)用該方法時出現(xiàn)錯誤(調(diào)用了一個沒有方法體的方法肯定會引起錯誤)。因此static和abstract不能同時修飾某個方法,即沒有所謂的類抽象方法。
(3) 抽象類不能創(chuàng)建實例,只能當(dāng)成父類來被繼承。從語義的角度來看,抽象類是從多個具體類中抽象出來的父類,它具有更高層次的抽象。
2. 相關(guān)面試題
1、抽象類必須要有抽象方法嗎?
抽象類不一定非要有抽象方法,抽象類中可以含有抽象方法和非抽象方法,可以只含有抽象方法,也可以只含有非抽象方法
public abstract class Person {
public void test(){
System.out.println("非抽象方法");
}
}
2、普通類和抽象類有哪些區(qū)別?
(1) 普通類不能包含抽象方法,抽象類可以包含抽象方法。
(2) 抽象類不能直接實例化,只能當(dāng)作父類被其他子類繼承,普通類可以直接實例化。
public abstract class Person {
// 抽象方法
public abstract void show();
// 非抽象方法
public void test(){
System.out.println("非抽象方法");
}
}
外部類的形式繼承抽象類Person
public class Student extends Person {
@Override
public void show() {
System.out.println("重寫抽象類中的抽象方法");
}
}
內(nèi)部類的形式繼承抽象類Person
public class Teacher {
public static void main(String[] args) {
Person person = new Person() {
@Override
public void show() {
System.out.println("重寫抽象類的抽象方法");
}
};
person.show();
}
}
3、抽象類能使用 final 修飾嗎?
當(dāng)使用abstract修飾類時,表明這個類只能被繼承;當(dāng)使用abstract修飾方法時,表明這個方法必須由子類提供實現(xiàn)(即重寫)。而final修飾的類不能被繼承,final修飾的方法不能被重寫。因此final和abstract永遠不能同時使用。
3. 接口
接口只是對一類事物的屬性和行為更高層次的抽象。對修改關(guān)閉,對擴展(不同的實現(xiàn)implements)開放,接口是對開閉原則的一種體現(xiàn)。
接口體:
interface 接口名{ 常量 抽象方法 靜態(tài)方法 默認(rèn)方法}interface 接口名
{
常量
抽象方法
靜態(tài)方法
默認(rèn)方法
}
3.1 接口中的常量
接口中的所有成員變量都默認(rèn)是由public static final修飾的,且由于接口里沒有構(gòu)造器和初始化塊,因此需要在定義Field時就指定初始值;
接口中的Field都是常量,經(jīng)常用來被定義常量的集合:
public interface FieldInterface {
/**
* 一年的天數(shù)
*/
int DAY = 365;
/**
* 一年的星期數(shù)
*/
int WEEK = 52;
/**
* 一年的月數(shù)
*/
int MONTH = 12;
}
public class Main {
public static void main(String[] args) {
/**
* 接口中定義的Field都是public static final修飾的常量,因此需要使用接口名來訪問
*/
System.out.println(FieldInterface.DAY);
}
}
一個類實現(xiàn)某個接口時,該類將會獲得接口中定義的Field :
public class FieldImpl implements FieldInterface {
// 將會繼承FieldInterface中定義的所有Field
}
public class Main {
public static void main(String[] args) {
System.out.println(FieldInterface.DAY);
// 使用實現(xiàn)類調(diào)用接口中的常量
System.out.println(FieldImpl.DAY);
}
}
3.2 接口中的方法
接口中的三種方法:
(1) 接口中的普通方法,默認(rèn)都是public abstract修飾的抽象方法,沒有方法體;
(2) 接口中的靜態(tài)方法,靜態(tài)方法必須要有實現(xiàn),且這個靜態(tài)方法只能用public修飾或不寫;
(3) 接口中的默認(rèn)方法,默認(rèn)方法必須要有實現(xiàn),用default修飾且不可省略,用來供子類繼承或重寫,二選一,但只能在實現(xiàn)類中使用或者實現(xiàn)類對象中使用;
分別展開舉例說明:
3.2.1 接口中的普通方法
接口中的普通方法,默認(rèn)都是public abstract修飾的抽象方法,沒有方法體;
- 接口的實現(xiàn)類如果是普通類,那么必須重寫接口中的所有抽象方法
- 接口的實現(xiàn)類如果是抽象類,那么可以不用重寫接口中的抽象方法
public interface BaseMethod {
/**
* 接口中的普通方法
* 以下方法默認(rèn)都是public abstract修飾的抽象方法,沒有方法體
*/
public abstract void show1();
abstract void show2();
public void show3();
void show4();
}
① 接口的實現(xiàn)類如果是普通類,那么必須重寫接口中的所有抽象方法:
public class BaseMethodImpl implements BaseMethod {
/**
* 當(dāng)一個類實現(xiàn)BaseMethod接口后,需要實現(xiàn)BaseMethod接口中的所有抽象方法
*/
@Override
public void show1() { }
@Override
public void show2() { }
@Override
public void show3() { }
@Override
public void show4() { }
}
② 接口的實現(xiàn)類如果是抽象類,那么可以不用重寫接口中的抽象方法:
public abstract class BaseMethodImpl2 implements BaseMethod {
/**
* 抽象類會繼承接口中定義的所有抽象方法和field
* 這個類仍然是抽象類,可以不用實現(xiàn)接口中所有的抽象方法
*/
@Override
public void show1() { }
}
3.2.2 接口中的靜態(tài)方法
- 調(diào)用形式:接口名.靜態(tài)方法名
- 接口中定義的靜態(tài)方法,不能被子接口繼承
- 接口中定義的靜態(tài)方法,不能被實現(xiàn)該接口的類繼承
public interface StaticMethod {
/**
* 接口中的靜態(tài)方法
* 接口中是可以定義靜態(tài)方法的,靜態(tài)方法必須要有實現(xiàn)。且這個靜態(tài)方法只能用public修飾或不寫。
*/
public static void test1(){
System.out.println("接口中定義靜態(tài)方法");
}
}
public class Main {
public static void main(String[] args) {
/**
* 接口中的靜態(tài)方法,只能通過接口名來調(diào)用,就像類的靜態(tài)方法一樣
*/
StaticMethod.test1();
}
}
① 接口中定義的靜態(tài)方法不能被子接口繼承:
public interface StaticMethod1 extends StaticMethod {
}
public class Main {
public static void main(String[] args) {
/**
* 編譯報錯,說明接口中定義的靜態(tài)方法不能被子接口繼承
*/
StaticMethod1.test1();
}
}
② 接口中定義的靜態(tài)方法不能被實現(xiàn)類繼承:
public class StaticMethodImpl implements StaticMethod {
}
public class Main {
public static void main(String[] args) {
/**
* 編譯報錯,說明接口中定義的靜態(tài)方法不能被實現(xiàn)類繼承
*/
StaticMethodImpl.test1();
}
}
3.2.3 接口中的默認(rèn)方法
- 接口中的默認(rèn)方法,不能通過接口名調(diào)用,需要通過接口實現(xiàn)類的實例進行訪問,即對象名.默認(rèn)方法名()
- 接口中的默認(rèn)方法,可以被實現(xiàn)類繼承,也可以在實現(xiàn)類中重寫
- 接口中的默認(rèn)方法,可以被子接口繼承,也可以在子接口中重寫
public interface DefaultMethod {
/**
* 接口中的默認(rèn)方法
* 用default修飾,不可省略,供子類繼承或重寫,二選一,但只能在實現(xiàn)類中使用或者實現(xiàn)類對象中使用
*/
public default void test2(){
System.out.println("接口中定義默認(rèn)方法");
}
}
① 接口中的默認(rèn)方法,可以被實現(xiàn)類繼承,也可以在實現(xiàn)類中重寫
public class DefaultMethodImpl implements DefaultMethod {
// 繼承接口中的方法
}
public class DefaultMethodImpl implements DefaultMethod {
// 重寫接口中的方法
@Override
public void test2() {
System.out.println("實現(xiàn)類重寫接口中的方法");
}
}
public class DefaultMethodImpl implements DefaultMethod {
// 重寫接口中的方法
@Override
public void test2() {
System.out.println("實現(xiàn)類重寫接口中的方法");
}
}
② 接口中的默認(rèn)方法,可以被子接口繼承,也可以在子接口中重寫
public interface DefaultMethod1 extends DefaultMethod {
// 繼承父接口中的方法
}
public interface DefaultMethod1 extends DefaultMethod {
// 重寫父接口中的方法
@Override
default void test2() {
System.out.println("子接口中重寫父接口中的方法");
}
}
3.3 接口中的接口和枚舉類
public interface Base {
/**
* 在接口中定義接口
*/
interface CommonConstant{
/**
* 一年的天數(shù)
*/
int DAY = 365;
/**
* 一年的星期數(shù)
*/
int WEEK = 52;
/**
* 一年的月數(shù)
*/
int MONTH = 12;
/**
* 在接口中定義靜態(tài)方法
*/
static void show() {
System.out.println("在接口中定義接口");
}
}
/**
* 在接口中定義枚舉類
*/
@AllArgsConstructor
enum WhiteStatusEnum {
/**
* 未加白
*/
NO_WHITE("未加白", "未加白"),
/**
* 部分加白
*/
PART_WHITE("部分加白", "部分加白"),
/**
* 全部加白
*/
ALL_WHITE("全部加白", "全部加白");
@Getter
private final String label;
@Getter
private final String value;
}
}
3.4 接口和抽象類
共同點:
(1) 接口和抽象類都不能被實例化,它們都位于繼承樹的頂端,用于被其他類實現(xiàn)和繼承;
(2) 接口和抽象類都可以包含抽象方法,實現(xiàn)接口或繼承抽象類的普通子類都必須實現(xiàn)這些抽象方法;
(3) 接口和抽象類中都可以包括抽象方法和非抽象方法;
不同點:
(1) 接口里只能定義靜態(tài)常量Field,不能定義普通Field;抽象類里則既可以定義普通Field,也可以定義靜態(tài)常量Field。
(2) 接口里不包含構(gòu)造器;抽象類里可以包含構(gòu)造器,抽象類里的構(gòu)造器并不是用于創(chuàng)建對象,而是讓其子類調(diào)用這些構(gòu)造器來完成屬于抽象類的初始化操作。
(3) 接口里不能包含初始化塊;但抽象類則完全可以包含初始化塊。
(4) 一個類最多只能有一個直接父類,包括抽象類;但一個類可以直接實現(xiàn)多個接口,通過實現(xiàn)多個接口可以彌補Java單繼承的不足。
public class MethodImpl implements FieldInterface, MethodInterface {
}
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
SpringCloud Feign遠程調(diào)用實現(xiàn)詳解
Feign是Netflix公司開發(fā)的一個聲明式的REST調(diào)用客戶端; Ribbon負(fù)載均衡、 Hystrⅸ服務(wù)熔斷是我們Spring Cloud中進行微服務(wù)開發(fā)非?;A(chǔ)的組件,在使用的過程中我們也發(fā)現(xiàn)它們一般都是同時出現(xiàn)的,而且配置也都非常相似2022-11-11
Java實現(xiàn)PDF轉(zhuǎn)為Word文檔的示例代碼
眾所周知,PDF文檔除了具有較強穩(wěn)定性和兼容性外,?還具有較強的安全性,在工作中可以有效避免別人無意中對文檔內(nèi)容進行修改。本文將分為以下兩部分介紹如何在保持布局的情況下將PDF轉(zhuǎn)為Word文檔,希望對大家有所幫助2023-01-01
使用Spring Cloud Feign遠程調(diào)用的方法示例
這篇文章主要介紹了使用Spring Cloud Feign遠程調(diào)用的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-09-09
Unity&Springboot實現(xiàn)本地登陸驗證
本文主要介紹了Unity&Springboot服務(wù)器/本地登陸驗證,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07
SpringBoot+Mybatis plus實現(xiàn)多數(shù)據(jù)源整合的實踐
本文主要介紹了SpringBoot+Mybatis plus實現(xiàn)多數(shù)據(jù)源整合的實踐,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10

