Java
程序員都知道要面向接口編程,那 Java
中的接口除了定義接口方法之外還能怎么用你知道嗎?今天阿粉就來(lái)帶大家看一下 Java
中的接口還可以有哪些用法。
基本特性
我們先看一下接口的基本特性
- 接口的定義需要使用關(guān)鍵字
interface
; - 接口定義的所有方法默認(rèn)都是
public abstract
; - 當(dāng)一個(gè)具體的
class
去實(shí)現(xiàn)一個(gè)interface
時(shí),需要使用implements
關(guān)鍵字; - 接口之間是可以多繼承,而類是只能單繼承的;
如下所示,我們定義一個(gè)接口
package com.example.demo.inter;
import java.io.Serializable;
import java.util.RandomAccess;
/**
* <br>
* <b>Function:</b><br>
* <b>Author:</b>@author java 極客技術(shù)<br>
* <b>Date:</b>2022-09-24 17:38<br>
* <b>Desc:</b>無(wú)<br>
*/
public interface ITest extends Serializable, RandomAccess {
public abstract String sayHello();
String sayHello2();// public abstract 可以省略
}
默認(rèn)方法
在 JDK 8
之前接口是不支持默認(rèn)方法的,在 JDK 8
之后接口支持默認(rèn)方法,默認(rèn)方法采用關(guān)鍵詞 default
聲明。
public interface ITest extends Serializable, RandomAccess {
public abstract String sayHello();
String sayHello2();// public abstract 省略
// 默認(rèn)方法
default String sayHello3() {
return "hello3";
}
}
默認(rèn)方法跟抽象方法不一樣,接口中定義的抽象方法,當(dāng)接口被其他類實(shí)現(xiàn)的時(shí)候都需要全部實(shí)現(xiàn),但是默認(rèn)方法是不需要被實(shí)現(xiàn)就可以直接使用的,類似于直接調(diào)用父類的方法一樣,所以在很多時(shí)候,我們已經(jīng)繼承了一個(gè)類,還想有一個(gè)能用但是不想每個(gè)子類都實(shí)現(xiàn)的方法的時(shí)候,就可以考慮增加一個(gè)接口的默認(rèn)方法來(lái)使用,簡(jiǎn)單來(lái)說(shuō)就是實(shí)現(xiàn)類可以不覆寫(xiě) default
方法。
default
方法存在的目的是,在我們已經(jīng)完善的項(xiàng)目中,如果我們直接給一個(gè)接口增加一個(gè)方法,在沒(méi)有默認(rèn)方法的時(shí)候就需要給所有的實(shí)現(xiàn)類都實(shí)現(xiàn)對(duì)應(yīng)的方法,但是這個(gè)方法又不一定是每個(gè)實(shí)現(xiàn)類都需要的,所以這個(gè)時(shí)候默認(rèn)方法就很好的解決了這個(gè)問(wèn)題,我們只需要增加一個(gè)默認(rèn)方法,然后在需要使用的實(shí)現(xiàn)類中進(jìn)行實(shí)現(xiàn)或者使用就可以了,其他的實(shí)現(xiàn)類不需要改動(dòng)任何的代碼。
標(biāo)記
接口還有一個(gè)很常見(jiàn)的功能那就是標(biāo)記功能,這么說(shuō)可能你沒(méi)有印象,但是到提到序列化接口 java.io.Serializable;
你肯定知道,我們經(jīng)常在對(duì)應(yīng)的 POJO
中都會(huì)實(shí)現(xiàn)這個(gè)序列化接口,而這個(gè)序列化的接口如果看過(guò)源碼的小伙伴肯定知道里面是沒(méi)有內(nèi)容的。
同樣的功能除了序列化的接口,類似的空接口還有很多,比如 java.util.RandomAccess
也是空接口,之前阿粉也寫(xiě)過(guò)關(guān)于 RandomAccess
這個(gè)接口的用途,感興趣的可以再去看看。 RandomAccess 明明是個(gè)空接口,能有什么用呢?
通過(guò)源碼我們可以知道 RandomAccess
是用來(lái)標(biāo)識(shí)子類是否實(shí)現(xiàn)了該接口,如果實(shí)現(xiàn)了則走實(shí)現(xiàn)了的邏輯,沒(méi)有實(shí)現(xiàn)就走沒(méi)有實(shí)現(xiàn)的邏輯,所以我們?cè)谌粘i_(kāi)發(fā)中也可以利用這個(gè)特性,當(dāng)我們有不同的子類需要根據(jù)情況進(jìn)行不同的實(shí)現(xiàn)邏輯的時(shí)候就可以采用定義一個(gè)空接口來(lái)標(biāo)記一下,方便后面的處理。
靜態(tài)方法
跟默認(rèn)方法一樣,JDK 8
還支持在接口中增加靜態(tài)方法,雖然說(shuō)在接口中定義靜態(tài)方法的做法不常見(jiàn),但是當(dāng)需要使用的時(shí)候也是可以支持的,避免在創(chuàng)建一個(gè)單獨(dú)的工具類,跟在類中定義的靜態(tài)方法一樣,我們可以直接通過(guò)接口名稱引用靜態(tài)方法,當(dāng)然靜態(tài)變量也是可以的,使用方法一樣。
public interface ITest extends Serializable, RandomAccess {
public abstract String sayHello();
String sayHello2();// public abstract 可以省略
default String sayHello3() {
System.out.println(sayHello4());
return "hello3";
}
public static String sayHello4() {
return "hello4";
}
}
私有方法
大家有沒(méi)有注意到,上面不管是默認(rèn)方法還是靜態(tài)方法其實(shí)都是 public
公開(kāi)的,可以讓實(shí)現(xiàn)類或者其他類直接使用,那有沒(méi)有可能在接口中定義一個(gè)私有方法呢?在 JDK 9
之前是不可以的,JDK 9
卻支持了,如下所示
private void privateMethod() {
System.out.println("private私有方法被調(diào)用");
}
private static void privateStaticMethod() {
System.out.println("private私有靜態(tài)方法被調(diào)用");
}
從官方的文檔中我們可以找到下面的描述,在 JDK 9
中接口支持私有方法,主要用于不同的非抽象方法中共享代碼。
我們可以看到在 JDK 9
這樣寫(xiě)是可以的
但是在 JDK8
就不行了,是無(wú)法編譯通過(guò)的,會(huì)提示不允許使用 private
修飾符。
總結(jié)
今天阿粉給大家總結(jié)了一個(gè)接口的使用方法,后面在日常的開(kāi)發(fā)中我們不單單只是在接口中定義抽象方法,也可以根據(jù)需求增加默認(rèn)方法或者私有方法,以及在需要用到標(biāo)記的時(shí)候也可以通過(guò)定義一個(gè)空接口來(lái)實(shí)現(xiàn),怎么樣是不是很棒,感覺(jué)動(dòng)起來(lái)吧。最后覺(jué)得我們的文章有幫助,歡迎一鍵三連。
本文由mdnice多平臺(tái)發(fā)布