Java 8:使用交替接口公开的类型安全地图生成器
动态展示您的课程
当我是Java新手时,我记得当时想过应该有一种方法可以删除或隐藏我不想公开的类中的方法。 就像用private
方法或类似方法覆盖public
方法一样(哪种情况是不可能的,也不应该是不可能的)。 显然,今天,我们都知道,通过暴露
interface
。
公爵和尖顶露出另一种样子……
通过使用名为Alternating Interface Exposure的方案,我们可以动态查看类的方法并输入安全类型,以便同一类可以强制实施应该使用的模式。
让我举个例子。 假设我们有一个Map
构建器,可以在构建实际Map
之前先相继添加键和值来调用它。 Alternating Interface Exposure方案使我们能够确保调用key()
方法和value()
的次数完全相同,并且只有在存在该调用时, build()
方法才可调用(例如在IDE中可见)。键和值一样多。
我正在参与的开源项目Speedment中使用了Alternating Interface Exposure方案。 在Speedment中,例如,在构建类型安全的Tuple时使用该方案,随后在向TupleBuilder
添加元素之后将构建该类型安全的Tuple 。 这样,如果我们编写TupleBuilder.builder().add("Meaning of Life).add(42).build()
,我们可以得到类型化的Tuple2<String, Integer>
= {“生命的含义”,42} TupleBuilder.builder().add("Meaning of Life).add(42).build()
。
使用动态地图生成器
我在以前的一些文章中(例如这里 )多次写过关于Builder模式的文章,如果您不熟悉这个概念,我鼓励您在阅读之前重新阅读有关此问题的文章。
当前的任务是产生一个Map
构建器,它使用许多上下文相关的接口动态地公开许多实现方法。 此外,构建器应在首次使用它们时“学习”其键/值类型,然后对其余条目实施相同类型的键/值。
这是一个示例,说明一旦开发人员如何在代码中使用该构建器:
public static void main(String[] args) {// Use the type safe builderMap<Integer, String> map = Maps.builder().key(1) // The key type is decided here for all following keys.value("One") // The value type is decided here for all following values.key(2) // Must be the same or extend the first key type.value("Two") // Must be the same type or extend the first value type.key(10).value("Zehn'") // And so on....build(); // Creates the map!// Create an empty mapMap<String, Integer> map2 = Maps.builder().build();}}
在上面的代码中,一旦我们开始通过调用key(1)
使用Integer,构建器将仅接受作为Integer
实例的其他键。 值也是如此。 一旦我们调用value("one")
,就只能使用作为String
实例的对象。 例如,如果尝试写入value(42)
而不是value("two")
,我们将立即在IDE中看到错误。 另外,当我们使用代码完成功能时,大多数IDE:都将能够自动选择合适的候选对象。
让我详细说明一下:
初次使用
该构建器是使用Maps.builder()
方法创建的,返回的初始视图允许我们调用:
build()
生成一个空的Map
(如上面的第二个“空地图”示例)key(K key)
,该密钥将密钥添加到构建器并确定所有后续密钥的类型(= K)(例如上述key(1)
)
一旦调用了初始key(K key)
,该构建器的另一个视图将显示为仅公开:
value(V value)
,它向构建器添加一个值,并为所有后续值(如value("one")
)决定类型(= V)
注意,由于键和值的数量不同, build()
方法不会在此状态下公开。 编写Map.builder().key(1) .build() ;
完全是非法的,因为没有与key 1
关联的值。
后续用法
现在已经确定了键和值类型,构建器将根据要调用的key()
或value()
在显示的两个交替接口之间进行切换。 如果调用key()
,则公开value()
;如果调用value()
,则公开key()
和build()
。
建造者
一旦确定类型,这是构建器使用的两个交替接口:
public interface KeyBuilder<K, V> {ValueBuilder<K, V> key(K k);Map<K, V> build();}
public interface ValueBuilder<K, V> {KeyBuilder<K, V> value(V v);}
请注意,一个接口如何返回另一个接口,从而导致暴露的交替接口无限流动。 这是使用交替接口的实际构建器:
public class Maps<K, V> implements KeyBuilder<K, V>, ValueBuilder<K, V> {private final List<Entry<K, V>> entries;private K lastKey;public Maps() {this.entries = new ArrayList<>();}@Overridepublic ValueBuilder<K, V> key(K k) {lastKey = k;return (ValueBuilder<K, V>) this;}@Overridepublic KeyBuilder<K, V> value(V v) {entries.add(new AbstractMap.SimpleEntry<>(lastKey, v));return (KeyBuilder<K, V>) this;}@Overridepublic Map<K, V> build() {return entries.stream().collect(toMap(Entry::getKey, Entry::getValue));}public static InitialKeyBuilder builder() {return new InitialKeyBuilder();}}
我们看到实现类实现了两个交替接口,但是仅根据调用key()
或value()
才返回其中一个接口。 我通过创建两个初始帮助类来“欺骗”一点,这两个初始帮助类负责尚未确定键和值类型的初始阶段。 为了完整起见,下面还显示了两个“欺诈”类:
public class InitialKeyBuilder {public <K> InitialValueBuilder<K> key(K k) {return new InitialValueBuilder<>(k);}public <K, V> Map<K, V> build() {return new HashMap<>();}}
public class InitialValueBuilder<K> {private final K k;public InitialValueBuilder(K k) {this.k = k;}public <V> KeyBuilder<K, V> value(V v) {return new Maps<K, V>().key(k).value(v);}}
后面的类以与主构建器类似的方式工作,即InitialKeyBuilder
返回InitialValueBuilder
,而InitialValueBuilder
创建一个类型化的构建器,该生成器可以通过交替返回KeyBuilder
或ValueBuilder
来无限期使用。
结论
当您需要类的类型安全和上下文感知模型时,“ 交替接口暴露”方案很有用。 您可以使用此方案为您的类制定和实施许多规则。 这些类的使用将更加直观,因为上下文相关的模型及其类型一直传播到IDE。 该模式还提供了更强大的代码,因为在设计阶段就很早就发现了潜在的错误。 我们将在编码时看到潜在的错误,而不是失败的测试或应用程序错误。
翻译自: https://www.javacodegeeks.com/2016/03/java-8-type-safe-map-builder-using-alternating-interface-exposure.html
Java 8:使用交替接口公开的类型安全地图生成器相关推荐
- java 交替_Java 8:使用交替接口公开的类型安全地图生成器
java 交替 动态展示您的课程 当我还是Java新手时,我记得当时以为应该有一种方法可以删除或隐藏我不想公开的类中的方法. 就像用private方法或类似方法覆盖public方法一样(哪种情况是不可 ...
- Java——okhttp3调用API接口
Java--okhttp3调用API接口 官方网站 本篇以java调用有课API接口为例,签名需要以map的key进行字典排序之后进行sha1加密算法后得出.有课API文档地址:https://pos ...
- java focuslistene_Java:FocusListener接口
有了ActionListener事件监听器,就一定要有FocusListener焦点事件监听器. FocusListener接口所在包 FocusListener接口在event包中,即在开头引入该包 ...
- java如何定义一个接口inf_java.抽象、接口
抽象 如果父类当中的方法不确定如何进行{}方法体实现,那么这就应该是一个抽象方法 定义 抽象方法:在返回值前加上abstract关键字,然后去掉大括号,分号直接结束. 抽象类:抽象方法所在的类,必须是 ...
- 【Android 应用开发】Android 网络编程 API笔记 - java.net 包相关 接口 api
Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...
- Java™ 教程(Queue接口)
Queue接口 Queue是在处理之前保存元素的集合,除了基本的Collection操作外,队列还提供额外的插入.删除和检查操作,Queue接口如下. public interface Queue&l ...
- Java中的某些接口为什么没有任何方法?
java中,有些接口内部没有声明任何方法,也就是说,实现这些接口的类不需要重写任何方法. 这些没有任何方法声明的接口又被叫做标识接口.标识接口对实现它的类没有任何语义上的要求,仅仅充当标识的作用,用来 ...
- Java中Collection集合接口
在Java中有数组,但数组不能存储引用变量.所以数组用得不是很多,一般Java中用继承Collection接口的实现类比较多.其中List接口和Set接口继承了Collection接口,而Map接口并 ...
- java hashedmap_Java基础 - Map接口的实现类 : HashedMap / LinkedHashMap /TreeMap 的构造/修改/遍历/ 集合视图方法/双向迭代输出...
import java.util.*; /**一:Collection接口的 * Map接口: HashMap(主要实现类) : HashedMap / LinkedHashMap /TreeMap ...
最新文章
- 【vue】ios中从详情页中返回到列表页出现空白的问题
- 解决Tensorflow2.0 tf.keras.Model.load_weights() 报错处理问题
- java8 supplier 接口
- web容器(02):tomcat配置监控
- python中的set方法_Python中set与frozenset方法和区别详解
- 活动事务日志以及事务的类型
- 【bzoj4753】[Jsoi2016]最佳团体 分数规划+树形背包dp
- 我的第九个java程序--spring和mybatis整合(java project)
- HDU 6706 huntian oy(杜教筛 + 一些定理)题解
- java方法前面加上x_@Autowired 写在构造方法上
- 模糊控制算法在MATLAB/SIMULINK中的应用
- 数据可视化:Metabase
- 用计算机信息术语感恩老师,感谢师恩、感恩老师的对联
- time+dd测试硬盘读写速度
- ATmega16 单片机 AVR单片机 直流电机调速器
- 手机连上电脑热点发现网络不可用,怎么办?
- python opencv Shi-Tomasi 角点检测和特征跟踪
- 决策树--信息增益、信息增益比、Geni指数的理解
- uniGUI获取设备信息
- VUE(四):引入iview
热门文章
- 到底什么是分布式系统
- 漫画:什么是MD5算法
- 3-1 Apache Shiro权限管理框架介绍
- mysql数据横表变成竖表_MySQL中横表和竖表相互转换
- springboot使用ImportBeanDefinitionRegistrar 动态注册bean
- 基于openfire源码开发插件
- POJ1321(DFS)
- 自动配置jdk_JDK 15中自动自动发送更好的NullPointerException消息
- posman mocks_使用Mocks进行需求驱动的软件开发
- java ldap操作实例_Java Spring Security示例教程中的2种设置LDAP Active Directory身份验证的方法...