java8 default methods 默认方法的概念与代码解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介:

一、基本概念  

      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.
      默认方法使您能够添加新的功能到你现有库的接口中,并确保与采用老版本接口编写的代码的二进制兼容性。

    什么是默认方法(default methods)
    即接口可以有实现方法,而且不需要实现类去实现其方法。只需在方法名前面加个default关键字即可,这些方法默认是

    为什么要有默认方法
    为什么要有这个特性?首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的java 8之前的集合框架没有foreach方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题

二、 java 8抽象类与接口的区别
    相同点:
    1.都是抽象类型;
    2.都可以有实现方法(java8才可以)
    3.都可以不需要实现类或者继承者去实现所有方法

    不同点
    1.抽象类不可以多重继承,接口可以(无论是多重类型继承还是多重行为继承);
    2.抽象类和接口所反映出的设计理念不同。其实抽象类表示的是"is-a"关系,接口表示的是"like-a"关系;
    3.接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值;抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。

三、多重继承的冲突说明
    由于同一个方法可以从不同接口引入,自然而然的会有冲突的现象,默认方法判断冲突的规则如下:
    1.一个声明在类里面的方法优先于任何默认方法(classes always win)
    2.否则,则会优先选取最具体的实现,比如下面的例子 B重写了A的hello方法。

四、如何扩展或实现带有默认方法的接口?

     当前扩展一个默认方法的接口时,你可以采用以下三种方式:

     1:让扩展类继承默认方法,根据不管是否存在默认方法

     2:重新声明默认方法,使其变为一个抽象方法(注意,扩展类的实现类必须实现此方法)

     3:重新定义默认方法,覆盖(override)父类的默认方法

五、默认方法样例代码

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();
		// 显示当前日期时间
		System.out.println(client.toString());
		// 设置日期
		client.setTime(11, 12, 22);
		System.out.println(client);
		// 设置时间
		client.setDate(2012, 11, 12);
		System.out.println(client);

		System.out.println("Time in Asia/Shanghai: "
				+ client.getZonedDateTime("Asia/Shanghai").toString());
	}
}

六、整合默认方法、静态方法到已经存在的接口

    默认方法使您能够添加新的功能到已经存在的接口,确保与采用老版本这些接口编写的代码的二进制兼容性。特别是,默认的方法使您能够在已经存在的接口中添加使用lambda表达式作为参数的方法。下面的样例代码说明通过默认方法和静态方法,Comparator 接口是如何提供丰富的功能的。

  在java8中,Compartor接口提供了丰富的功能,提供了差不多近20个默认或静态方法,在以前的版本中仅仅提供了compare(T o1, T o2)一个比较接口方法

    下面的代码是有关扑克牌游戏中的洗牌,针对牌排序,打散,发牌的部分源代码

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;

//先根据rank,再根据suit进行比较
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;

//扑克牌实现类
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();
	}

	//实现比较接口
	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;

//牌桌实现类
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;

		//根据玩家的个数,每个玩家分到的扑克牌数进行分牌
		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("-------------------------------");
		}
	}
}
目录
相关文章
|
8天前
|
人工智能 自然语言处理 Java
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
FastExcel 是一款基于 Java 的高性能 Excel 处理工具,专注于优化大规模数据处理,提供简洁易用的 API 和流式操作能力,支持从 EasyExcel 无缝迁移。
57 9
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
|
15天前
|
存储 缓存 Java
Java 并发编程——volatile 关键字解析
本文介绍了Java线程中的`volatile`关键字及其与`synchronized`锁的区别。`volatile`保证了变量的可见性和一定的有序性,但不能保证原子性。它通过内存屏障实现,避免指令重排序,确保线程间数据一致。相比`synchronized`,`volatile`性能更优,适用于简单状态标记和某些特定场景,如单例模式中的双重检查锁定。文中还解释了Java内存模型的基本概念,包括主内存、工作内存及并发编程中的原子性、可见性和有序性。
Java 并发编程——volatile 关键字解析
|
13天前
|
Java 数据库连接 Spring
反射-----浅解析(Java)
在java中,我们可以通过反射机制,知道任何一个类的成员变量(成员属性)和成员方法,也可以堆任何一个对象,调用这个对象的任何属性和方法,更进一步我们还可以修改部分信息和。
|
1月前
|
Java 编译器
Java 泛型详细解析
本文将带你详细解析 Java 泛型,了解泛型的原理、常见的使用方法以及泛型的局限性,让你对泛型有更深入的了解。
52 2
Java 泛型详细解析
|
1月前
|
存储 算法 Java
Java内存管理深度解析####
本文深入探讨了Java虚拟机(JVM)中的内存分配与垃圾回收机制,揭示了其高效管理内存的奥秘。文章首先概述了JVM内存模型,随后详细阐述了堆、栈、方法区等关键区域的作用及管理策略。在垃圾回收部分,重点介绍了标记-清除、复制算法、标记-整理等多种回收算法的工作原理及其适用场景,并通过实际案例分析了不同GC策略对应用性能的影响。对于开发者而言,理解这些原理有助于编写出更加高效、稳定的Java应用程序。 ####
|
1月前
|
存储 监控 算法
Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
|
1月前
|
Java 数据库连接 开发者
Java中的异常处理机制:深入解析与最佳实践####
本文旨在为Java开发者提供一份关于异常处理机制的全面指南,从基础概念到高级技巧,涵盖try-catch结构、自定义异常、异常链分析以及最佳实践策略。不同于传统的摘要概述,本文将以一个实际项目案例为线索,逐步揭示如何高效地管理运行时错误,提升代码的健壮性和可维护性。通过对比常见误区与优化方案,读者将获得编写更加健壮Java应用程序的实用知识。 --- ####
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
92 2
|
14天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
14天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

推荐镜像

更多