欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java8中的默認(rèn)方法(面試者必看)

 更新時間:2020年11月26日 11:20:18   作者:Silently9527  
這篇文章主要介紹了Java8中的默認(rèn)方法(面試者必看),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

背景

在Java8之前,定義在接口中的所有方法都需要在接口實現(xiàn)類中提供一個實現(xiàn),如果接口的提供者需要升級接口,添加新的方法,那么所有的實現(xiàn)類都需要把這個新增的方法實現(xiàn)一遍,如果說所有的實現(xiàn)類能夠自己控制的話,那么還能接受,但是現(xiàn)實情況是實現(xiàn)類可能不受自己控制。比如說Java中的集合框架中的List接口添加一個方法,那么Apache Commons這種框架就會很難受,必須修改所有實現(xiàn)了List的實現(xiàn)類

現(xiàn)在的接口有哪些不便

向已經(jīng)發(fā)布的接口中添加新的方法是問題的根源,一旦接口發(fā)生變化,接口的實現(xiàn)者都需要更新代碼,實現(xiàn)新增的接口
接口中有些方法是可選的,不是所有的實現(xiàn)者都需要實現(xiàn),這個時候?qū)崿F(xiàn)類不得不實現(xiàn)一個空的方法,或者是提供一個Adapter對接口中所有的方法做空實現(xiàn),在Spring中我們可看到很多這種例子,比如WebMvcConfigurerAdapter

@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {

 @Override
 public void configurePathMatch(PathMatchConfigurer configurer) {
 }


 @Override
 public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
 }

 @Override
 public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
 }
 
 省略其他代碼...
}

在Java8以后這些類都被標(biāo)注成了過期@Deprecated

默認(rèn)方法的簡介

為了解決上述問題,在Java8中允許指定接口做默認(rèn)實現(xiàn),未指定的接口由實現(xiàn)類去實現(xiàn)。如何標(biāo)識出接口是默認(rèn)實現(xiàn)呢?方法前面加上default關(guān)鍵字。比如Spring中的WebMvcConfigurer

public interface WebMvcConfigurer {

 default void configurePathMatch(PathMatchConfigurer configurer) {
 }

 default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
 }

 default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
 }
 
 省略其他代碼...
}

從現(xiàn)在看來,可能大家都會有個疑問,默認(rèn)方法和抽象類有什么區(qū)別呢?

  • 默認(rèn)方法不能有實例變量,抽象類可以有
  • 一個類只能繼承一個抽象類,當(dāng)時可以實現(xiàn)多個接口

默認(rèn)方法的使用場景

可選方法

為接口提供可選的方法,給出默認(rèn)實現(xiàn),這樣實現(xiàn)類就不用顯示的去提供一個空的方法;這種場景剛才我們在上面已經(jīng)說到了,spring中有大量的例子

實現(xiàn)多繼承

繼承是面向?qū)ο蟮奶匦灾?,在Java中一直以來都是單繼承的原則,Java8中默認(rèn)方法為實現(xiàn)多繼承提供了可能(由于接口中不能有實例對象,所以能夠抽象的到接口中的行為一般都是比較小的模塊);從個人的經(jīng)歷來看,做游戲是訓(xùn)練自己面向?qū)ο笏季S的最好方式(以后有機會分享一下小游戲的制作),因為現(xiàn)在大部分學(xué)Java的同學(xué)學(xué)完Java基礎(chǔ)后就直接進入JavaWeb的學(xué)習(xí),整合各種框架,只能在通用的三層架構(gòu)(Controller、Service、Dao)中寫自己的邏輯。

相信很多人在都做個坦克大戰(zhàn)的游戲,如果用Java8中的默認(rèn)方法如何設(shè)計好多繼承呢?

這里我們舉個簡單的例子,定義了三個接口:

  1. Moveable:允許移動的物體,把移動的邏輯放入到這個接口中的默認(rèn)方法
  2. Attackable: 允許攻擊的物體,把攻擊的通用邏輯放入到默認(rèn)方法,不通用的邏輯通過模板方法給實現(xiàn)類處理
  3. Location: 獲取物體的坐標(biāo)

通過這些接口的組合方式,我們就可以為游戲創(chuàng)建不同的實現(xiàn)類,比如說坦克、草地、墻壁...

解決默認(rèn)方法沖突規(guī)則(面試者必看)

通過上面的例子,我們體驗的默認(rèn)方法給我們帶來了多繼承的便利,但是讓我們思考下,如果出現(xiàn)了不同的類出現(xiàn)的相同簽名的默認(rèn)方法,實際在運行的時候應(yīng)該如何選擇呢?客官不慌,有辦法的

  • 類中的方法優(yōu)先級最高。如果類或者父類(抽象類也OK)中聲明了相同簽名的方法,那么優(yōu)先級最高
  • 如果第一條無法確定,那么最具體的的實現(xiàn)的默認(rèn)方法;很繞,舉例子:B接口繼承了A,B就更加具體,那么B中的方法優(yōu)先級最高
  • 如果上面兩個都無法判斷,那么編譯會報錯,需要在實現(xiàn)接口,然后手動顯式調(diào)用
public class C implements A, B {
 void pint() {
  B.supper.print(); // 顯式調(diào)用
 }
}

菱形繼承問題

為了說明上面的三個原則,我們直接來看看最復(fù)雜的菱形繼承問題

public interface A {
 default void print(){
  System.out.println("Class A");
 }
}

public interface B extend A {}

public interface C extend A {}

public class D implement B, C {
 public static void main(String[] args) {
  new D().print()
 }
}

這種情況下B,C都沒有自己的實現(xiàn),實際上就只有A有實現(xiàn),那么會打印Class A

如果說這個時候把接口B接口改一下

public interface B extends A {
 default void print(){
  System.out.println("Class B");
 }
}

根據(jù)原則(2),B繼承于A,更加具體,所以打印結(jié)果應(yīng)該是B
如果說把接口C修改一下

public interface C extends A {
 default void print(){
  System.out.println("Class C");
 }
}

這時候我們發(fā)現(xiàn)編譯報錯,需要我們自己手動指定,修改D中的代碼

public class D implements B, C {

 @Override
 public void print() {
  C.super.print();
 }

 public static void main(String[] args) {
  new D().print();
 }
}

總結(jié)

  • Java8中的默認(rèn)方法需要使用default來修飾
  • 默認(rèn)方法的使用場景可選方法和多繼承
  • 三個原則解決相同簽名的默認(rèn)方法沖突問題

到此這篇關(guān)于Java8中的默認(rèn)方法(面試者必看)的文章就介紹到這了,更多相關(guān)Java8 默認(rèn)方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論