新聞中心
一、基本概念

創(chuàng)新互聯(lián)建站專注于都昌企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,商城系統(tǒng)網(wǎng)站開發(fā)。都昌網(wǎng)站建設(shè)公司,為都昌等地區(qū)提供建站服務(wù)。全流程按需策劃,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)建站專業(yè)和態(tài)度為您提供的服務(wù)
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)。然而,對于已經(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)撲克牌游戲中的洗牌,針對牌排序,打散,發(fā)牌的部分源代碼
- package defaultmethods;
- //撲克牌接口類
- public interface Card extends Comparable
{ - 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
getCards(); - Deck deckFactory();
- int size();
- void addCard(Card card);
- void addCards(List
cards); - void addDeck(Deck deck);
- void shuffle();
- void sort();
- void sort(Comparator
c); - String deckToString();
- Map
deal(int players, int numberOfCards) - throws IllegalArgumentException;
- }
- package defaultmethods;
- import java.util.Comparator;
- //先根據(jù)rank,再根據(jù)suit進(jìn)行比較
- public class SortByRankThenSuit implements Comparator
{ - 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
entireDeck; - public StandardDeck(List
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
()); - }
- public int size() {
- return entireDeck.size();
- }
- public List
getCards() { - return entireDeck;
- }
- public void addCard(Card card) {
- entireDeck.add(card);
- }
- public void addCards(List
cards) { - entireDeck.addAll(cards);
- }
- public void addDeck(Deck deck) {
- List
listToAdd = deck.getCards(); - entireDeck.addAll(listToAdd);
- }
- public void sort() {
- Collections.sort(entireDeck);
- }
- public void sort(Comparator
c) { - Collections.sort(entireDeck, c);
- }
- public void shuffle() {
- Collections.shuffle(entireDeck);
- }
- //為每位玩家分牌
- public Map
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
> 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
> to Map - Map
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
map=myDeck.deal(4, 11); - for(Map.Entry
item:map.entrySet()){ - System.out.println(item.getKey());
- System.out.println(item.getValue());
- System.out.println("-------------------------------");
- }
- }
- }
七、參考
http://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html
http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
http://docs.oracle.com/javase/tutorial/java/TOC.html
文章標(biāo)題:Java8defaultmethods默認(rèn)方法的概念與代碼解析
文章來源:http://fisionsoft.com.cn/article/dhcpipo.html


咨詢
建站咨詢
