溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

在Java8 default methods中默認(rèn)方法的概念與代碼是怎樣的

發(fā)布時(shí)間:2021-09-18 17:22:37 來源:億速云 閱讀:116 作者:柒染 欄目:編程語言

這篇文章給大家介紹在Java8 default methods中默認(rèn)方法的概念與代碼是怎樣的,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

一、基本概念  

Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.

默認(rèn)方法使您能夠添加新的功能到你現(xiàn)有庫的接口中,并確保與采用老版本接口編寫的代碼的二進(jìn)制兼容性。

什么是默認(rèn)方法(default methods)

即接口可以有實(shí)現(xiàn)方法,而且不需要實(shí)現(xiàn)類去實(shí)現(xiàn)其方法。只需在方法名前面加個(gè)default關(guān)鍵字即可,這些方法默認(rèn)是

為什么要有默認(rèn)方法

為什么要有這個(gè)特性?首先,之前的接口是個(gè)雙刃劍,好處是面向抽象而不是面向具體編程,缺陷是,當(dāng)需要修改接口時(shí)候,需要修改全部實(shí)現(xiàn)該接口的類,目前的java 8之前的集合框架沒有foreach方法,通常能想到的解決辦法是在JDK里給相關(guān)的接口添加新的方法及實(shí)現(xiàn)。然而,對(duì)于已經(jīng)發(fā)布的版本,是沒法在給接口添加新方法的同時(shí)不影響已有的實(shí)現(xiàn)。所以引進(jìn)的默認(rèn)方法。他們的目的是為了解決接口的修改與現(xiàn)有的實(shí)現(xiàn)不兼容的問題

二、 java 8抽象類與接口的區(qū)別

相同點(diǎn):

1.都是抽象類型;

2.都可以有實(shí)現(xiàn)方法(java8才可以)

3.都可以不需要實(shí)現(xiàn)類或者繼承者去實(shí)現(xiàn)所有方法

不同點(diǎn)

1.抽象類不可以多重繼承,接口可以(無論是多重類型繼承還是多重行為繼承);

2.抽象類和接口所反映出的設(shè)計(jì)理念不同。其實(shí)抽象類表示的是"is-a"關(guān)系,接口表示的是"like-a"關(guān)系;

3.接口中定義的變量默認(rèn)是public static final 型,且必須給其初值,所以實(shí)現(xiàn)類中不能重新定義,也不能改變其值;抽象類中的變量默認(rèn)是 friendly 型,其值可以在子類中重新定義,也可以重新賦值。

三、多重繼承的沖突說明

由于同一個(gè)方法可以從不同接口引入,自然而然的會(huì)有沖突的現(xiàn)象,默認(rèn)方法判斷沖突的規(guī)則如下:

1.一個(gè)聲明在類里面的方法優(yōu)先于任何默認(rèn)方法(classes always win)

2.否則,則會(huì)優(yōu)先選取***體的實(shí)現(xiàn),比如下面的例子 B重寫了A的hello方法。

四、如何擴(kuò)展或?qū)崿F(xiàn)帶有默認(rèn)方法的接口?

當(dāng)前擴(kuò)展一個(gè)默認(rèn)方法的接口時(shí),你可以采用以下三種方式:

1:讓擴(kuò)展類繼承默認(rèn)方法,根據(jù)不管是否存在默認(rèn)方法

2:重新聲明默認(rèn)方法,使其變?yōu)橐粋€(gè)抽象方法(注意,擴(kuò)展類的實(shí)現(xiàn)類必須實(shí)現(xiàn)此方法)

3:重新定義默認(rèn)方法,覆蓋(override)父類的默認(rèn)方法

五、默認(rèn)方法樣例代碼

import java.time.DateTimeException;  import java.time.LocalDateTime;  import java.time.ZoneId;  import java.time.ZonedDateTime;   public interface TimeClient {      void setTime(int hour, int minute, int second);       void setDate(int day, int month, int year);       void setDateAndTime(int day, int month, int year, int hour, int minute,              int second);       LocalDateTime getLocalDateTime();       static ZoneId getZoneId(String zoneString) {          try {              return ZoneId.of(zoneString);          } catch (DateTimeException e) {              System.err.println("Invalid time zone: " + zoneString                      + "; using default time zone instead.");              return ZoneId.systemDefault();          }      }       default ZonedDateTime getZonedDateTime(String zoneString) {          return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));      }  }
import java.time.LocalDate;  import java.time.LocalDateTime;  import java.time.LocalTime;  import java.util.ArrayList;  import java.util.Collections;  import java.util.Comparator;  import java.util.List;   public class SimpleTimeClient implements TimeClient {       private LocalDateTime dateAndTime;       public SimpleTimeClient() {          dateAndTime = LocalDateTime.now();      }       public void setTime(int hour, int minute, int second) {          LocalDate currentDate = LocalDate.from(dateAndTime);          LocalTime timeToSet = LocalTime.of(hour, minute, second);          dateAndTime = LocalDateTime.of(currentDate, timeToSet);      }       public void setDate(int year, int month, int day) {          LocalDate dateToSet = LocalDate.of(year, month, day);          LocalTime currentTime = LocalTime.from(dateAndTime);          dateAndTime = LocalDateTime.of(dateToSet, currentTime);      }       public void setDateAndTime(int year, int month, int day, int hour,              int minute, int second) {          LocalDate dateToSet = LocalDate.of(year, month, day);          LocalTime timeToSet = LocalTime.of(hour, minute, second);          dateAndTime = LocalDateTime.of(dateToSet, timeToSet);      }       public LocalDateTime getLocalDateTime() {          return dateAndTime;      }       public String toString() {          return dateAndTime.toString();      }       public static void main(String... args) {          TimeClient client = new SimpleTimeClient();          // 顯示當(dāng)前日期時(shí)間          System.out.println(client.toString());          // 設(shè)置日期          client.setTime(11, 12, 22);          System.out.println(client);          // 設(shè)置時(shí)間          client.setDate(2012, 11, 12);          System.out.println(client);           System.out.println("Time in Asia/Shanghai: "                 + client.getZonedDateTime("Asia/Shanghai").toString());      }  }

六、整合默認(rèn)方法、靜態(tài)方法到已經(jīng)存在的接口

默認(rèn)方法使您能夠添加新的功能到已經(jīng)存在的接口,確保與采用老版本這些接口編寫的代碼的二進(jìn)制兼容性。特別是,默認(rèn)的方法使您能夠在已經(jīng)存在的接口中添加使用lambda表達(dá)式作為參數(shù)的方法。下面的樣例代碼說明通過默認(rèn)方法和靜態(tài)方法,Comparator 接口是如何提供豐富的功能的。

在java8中,Compartor接口提供了豐富的功能,提供了差不多近20個(gè)默認(rèn)或靜態(tài)方法,在以前的版本中僅僅提供了compare(T o1, T o2)一個(gè)比較接口方法

下面的代碼是有關(guān)撲克牌游戲中的洗牌,針對(duì)牌排序,打散,發(fā)牌的部分源代碼

package defaultmethods;   //撲克牌接口類  public interface Card extends Comparable<Card> {            public enum Suit {           DIAMONDS (1, "Diamonds"),           CLUBS    (2, "Clubs"   ),           HEARTS   (3, "Hearts"  ),           SPADES   (4, "Spades"  );                    private final int value;          private final String text;          Suit(int value, String text) {              this.value = value;              this.text = text;          }          public int value() {return value;}          public String text() {return text;}      }            public enum Rank {           DEUCE  (2 , "Two"  ),          THREE  (3 , "Three"),           FOUR   (4 , "Four" ),           FIVE   (5 , "Five" ),           SIX    (6 , "Six"  ),           SEVEN  (7 , "Seven"),          EIGHT  (8 , "Eight"),           NINE   (9 , "Nine" ),           TEN    (10, "Ten"  ),           JACK   (11, "Jack" ),          QUEEN  (12, "Queen"),           KING   (13, "King" ),          ACE    (14, "Ace"  );          private final int value;          private final String text;          Rank(int value, String text) {              this.value = value;              this.text = text;          }          public int value() {return value;}          public String text() {return text;}      }            public Card.Suit getSuit();      public Card.Rank getRank();  }
package defaultmethods;   import java.util.Comparator;  import java.util.List;  import java.util.Map;   //牌桌接口類  public interface Deck {            List<Card> getCards();      Deck deckFactory();      int size();      void addCard(Card card);      void addCards(List<Card> cards);      void addDeck(Deck deck);      void shuffle();      void sort();      void sort(Comparator<Card> c);      String deckToString();       Map<Integer, Deck> deal(int players, int numberOfCards)          throws IllegalArgumentException;   }
package defaultmethods;   import java.util.Comparator;   //先根據(jù)rank,再根據(jù)suit進(jìn)行比較  public class SortByRankThenSuit implements Comparator<Card> {      public int compare(Card firstCard, Card secondCard) {          int compVal = firstCard.getRank().value()                  - secondCard.getRank().value();          if (compVal != 0)              return compVal;          else             return firstCard.getSuit().value() - secondCard.getSuit().value();      }  }
package defaultmethods;   //撲克牌實(shí)現(xiàn)類  public class PlayingCard implements Card {       private Card.Rank rank;      private Card.Suit suit;       public PlayingCard(Card.Rank rank, Card.Suit suit) {          this.rank = rank;          this.suit = suit;      }       public Card.Suit getSuit() {          return suit;      }       public Card.Rank getRank() {          return rank;      }       public boolean equals(Object obj) {          if (obj instanceof Card) {              if (((Card) obj).getRank() == this.rank                      && ((Card) obj).getSuit() == this.suit) {                  return true;              } else {                  return false;              }          } else {              return false;          }      }       public int hashCode() {          return ((suit.value() - 1) * 13) + rank.value();      }       //實(shí)現(xiàn)比較接口      public int compareTo(Card o) {          return this.hashCode() - o.hashCode();      }       //重載toString      public String toString() {          return this.rank.text() + " of " + this.suit.text();      }       public static void main(String... args) {          new PlayingCard(Rank.ACE, Suit.DIAMONDS);          new PlayingCard(Rank.KING, Suit.SPADES);      }  }
package defaultmethods;   import java.util.ArrayList;  import java.util.Collections;  import java.util.Comparator;  import java.util.HashMap;  import java.util.List;  import java.util.Map;  import java.util.stream.Collectors;   //牌桌實(shí)現(xiàn)類  public class StandardDeck implements Deck {       //撲克牌列表      private List<Card> entireDeck;       public StandardDeck(List<Card> existingList) {          this.entireDeck = existingList;      }       public StandardDeck() {          this.entireDeck = new ArrayList<>();          for (Card.Suit s : Card.Suit.values()) {              for (Card.Rank r : Card.Rank.values()) {                  this.entireDeck.add(new PlayingCard(r, s));              }          }      }       public Deck deckFactory() {          return new StandardDeck(new ArrayList<Card>());      }       public int size() {          return entireDeck.size();      }       public List<Card> getCards() {          return entireDeck;      }       public void addCard(Card card) {          entireDeck.add(card);      }       public void addCards(List<Card> cards) {          entireDeck.addAll(cards);      }       public void addDeck(Deck deck) {          List<Card> listToAdd = deck.getCards();          entireDeck.addAll(listToAdd);      }       public void sort() {          Collections.sort(entireDeck);      }       public void sort(Comparator<Card> c) {          Collections.sort(entireDeck, c);      }       public void shuffle() {          Collections.shuffle(entireDeck);      }       //為每位玩家分牌      public Map<Integer, Deck> deal(int players, int numberOfCards)              throws IllegalArgumentException {          int cardsDealt = players * numberOfCards;          int sizeOfDeck = entireDeck.size();                    if (cardsDealt > sizeOfDeck) {              throw new IllegalArgumentException("Number of players (" + players                      + ") times number of cards to be dealt (" + numberOfCards                      + ") is greater than the number of cards in the deck ("                     + sizeOfDeck + ").");          }          //把牌分成幾份          int slices=players+1;          if(cardsDealt == sizeOfDeck)              slices=players;           //根據(jù)玩家的個(gè)數(shù),每個(gè)玩家分到的撲克牌數(shù)進(jìn)行分牌          Map<Integer, List<Card>> dealtDeck = entireDeck.stream().collect(                  Collectors.groupingBy(card -> {                      int cardIndex = entireDeck.indexOf(card);                      if (cardIndex >= cardsDealt)                          return (players + 1);                      else                         return (cardIndex % players) + 1;                  }));          System.out.println(dealtDeck);          // Convert Map<Integer, List<Card>> to Map<Integer, Deck>          Map<Integer, Deck> mapToReturn = new HashMap<>();           for (int i = 1; i < (slices + 1); i++) {              Deck currentDeck = deckFactory();              currentDeck.addCards(dealtDeck.get(i));              mapToReturn.put(i, currentDeck);          }          return mapToReturn;      }       public String deckToString() {          return this.entireDeck.stream().map(Card::toString)                  .collect(Collectors.joining("\n"));      }            public String toString(){          return deckToString();      }       public static void main(String... args) {          System.out.println("Creating deck:");          StandardDeck myDeck = new StandardDeck();                    myDeck.sort();          System.out.println("Sorted deck");          System.out.println(myDeck.deckToString());                    myDeck.shuffle();          myDeck.sort(new SortByRankThenSuit());          System.out.println("Sorted by rank, then by suit");          System.out.println(myDeck.deckToString());                    myDeck.shuffle();          myDeck.sort(Comparator.comparing(Card::getRank).thenComparing(                  Comparator.comparing(Card::getSuit)));          System.out.println("Sorted by rank, then by suit "                 + "with static and default methods");          System.out.println(myDeck.deckToString());           myDeck.sort(Comparator.comparing(Card::getRank).reversed()                  .thenComparing(Comparator.comparing(Card::getSuit).reversed()));          System.out.println("Sorted by rank reversed, then by suit "                 + "with static and default methods");          System.out.println(myDeck.deckToString());                    myDeck.shuffle();          myDeck.sort(              (firstCard, secondCard) ->                  firstCard.getRank().value() - secondCard.getRank().value()          );           System.out.println(myDeck.deckToString());                    myDeck.shuffle();          myDeck.sort(Comparator.comparing(Card::getRank));          System.out.println(myDeck.deckToString());                    Map<Integer, Deck> map=myDeck.deal(4, 11);          for(Map.Entry<Integer, Deck> item:map.entrySet()){              System.out.println(item.getKey());              System.out.println(item.getValue());              System.out.println("-------------------------------");          }      }  }

關(guān)于在Java8 default methods中默認(rèn)方法的概念與代碼是怎樣的就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI