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()方法创建的,返回的初始视图允许我们调用:

  1. build()生成一个空的Map (如上面的第二个“空地图”示例)
  2. key(K key) ,该密钥将密钥添加到构建器并确定所有后续密钥的类型(= K)(例如上述key(1)

一旦调用了初始key(K key) ,该构建器的另一个视图将显示为仅公开:

  1. 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创建一个类型化的构建器,该生成器可以通过交替返回KeyBuilderValueBuilder来无限期使用。

结论

当您需要类的类型安全和上下文感知模型时,“ 交替接口暴露”方案很有用。 您可以使用此方案为您的类制定和实施许多规则。 这些类的使用将更加直观,因为上下文相关的模型及其类型一直传播到IDE。 该模式还提供了更强大的代码,因为在设计阶段就很早就发现了潜在的错误。 我们将在编码时看到潜在的错误,而不是失败的测试或应用程序错误。

翻译自: https://www.javacodegeeks.com/2016/03/java-8-type-safe-map-builder-using-alternating-interface-exposure.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/354505.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nodejs面试题

1、为什么用Nodejs,它有哪些缺点&#xff1f; 事件驱动&#xff0c;通过闭包很容易实现客户端的生命活期。不用担心多线程&#xff0c;锁&#xff0c;并行计算的问题V8引擎速度非常快对于游戏来说&#xff0c;写一遍游戏逻辑代码&#xff0c;前端后端通用当然Nodejs也有一些缺点…

sts-bundle的使用_使用WS-Trust / STS采样器扩展JMeter

sts-bundle的使用JMeter没有对WS-Security或WS-Trust的任何内置支持&#xff0c;这使我为JMeter开发了此STS采样器–可以在负载测试STS时使任何人的生活变得更好。 首先&#xff0c;您需要拥有Apache JMeter发行版。 我正在使用v2.7。 然后&#xff0c;您可以从此处下载sts.sam…

001_jdk配置

配置JAVA_HOME,CLASSPATH,PATH 其中JAVA_HOME必须的 JAVA_HOMEE:\java\jdk1.8.0_77 CLASSPATH(告诉java程序运行时&#xff0c;你的类或者类库在哪里) .; E:\java\jdk1.8.0_77\lib\dt.jar;E:\java\jdk1.8.0_77\lib\tools.jar;E:\java\jdk1.8.0_77\jre\lib\rt.jar 改成变量 .;%J…

python -- join()

python -- join()pythonjoinos月似当时&#xff0c;人似当时否&#xff1f;总 在 python 中&#xff0c;一共有两个 join 方法&#xff0c;一个是 str.join(),另一个是 os.path.join() &#xff0c;这里只了解前一种 str.join(iterable) 官方文档 Return a string which is the…

Spark数据倾斜解决方案(转)

本文转发自技术世界&#xff0c;原文链接 http://www.jasongj.com/spark/skew/ Spark性能优化之道——解决Spark数据倾斜&#xff08;Data Skew&#xff09;的N种姿势 发表于 2017-02-28 | 更新于 2017-10-17 | 本文结合实例详细阐明了Spark数据倾斜的几种场景以及对应的解…

JavaParser入门:以编程方式分析Java代码

我最喜欢的事情之一是解析代码并对其执行自动操作。 因此&#xff0c;我开始为JavaParser做出贡献&#xff0c;并创建了两个相关项目&#xff1a; java-symbol-solver和Effectivejava 。 作为JavaParser的贡献者&#xff0c;我反复阅读了一些非常类似的问题&#xff0c;这些问…

GoldenGate Logdump基本使用

Logdump是GoldenGate复制软件中附带的一个工具软件&#xff0c;在OGG的目录下可以找到。这个工具主要用于分析OGG生成的队列文件&#xff0c;查找记录、统计队列文件中的数据等。 在OGG安装目录下执行logdump.exe or ./logdump即可进入命令行。 开始查找记录之前&#xff0c;先…

.bam.bai的意义_业务活动监视器(BAM)2.0带来的革命

.bam.bai的意义生产兼具精益和企业价值的中间件是一项艰巨的工作。 它要么不存在&#xff0c;要么需要创新的思维&#xff08;很多&#xff09;&#xff0c;并且需要在实现中反复进行。 业务风险很大&#xff0c;但是如果您做对了&#xff0c;它就会使您领先于其他任何公司。 这…

数据结构和算法之排序五:选择排序

我们上一篇谈到了冒泡排序&#xff0c;其实我也说了&#xff0c;这两个排序方式何其相似&#xff0c;如果掌握了冒泡排序再来进行选择排序的理解我觉得完全没有太大的问题。那么什么叫做选择排序呢&#xff1f;我们可以理解为矮子里面挑高个&#xff0c;比如说呀有一个富翁来到…

Visual Studio Code使用问题

1、打开vscode黑屏 右击vscode快捷方式–>属性–>兼容性—>兼容模式打钩 重启vscode就可以了。 2、vscode终端没有显示路径&#xff0c;不能输入 显示如下图 则关闭VS Code ,右键单击VS Code 图标&#xff0c;选择属性->兼容性&#xff0c;取消勾选 已兼容模式运…

Java社区调查结果:74%的开发人员希望减少详细程度

一个新的JDK增强建议&#xff08;JEP&#xff09;在Java社区中风起云涌&#xff1a;JEP286。该建议建议在Java的未来版本中引入局部变量类型推断&#xff0c;以简化Java应用程序的编写。 在下面的文章中&#xff0c;我们将解释它的含义以及它将如何影响您的代码。 新帖&#…

coherence安装_Oracle Coherence:分布式数据管理

coherence安装本文介绍如何使用Oracle Coherence提供分布式&#xff08;分区&#xff09;数据管理。 在下面的示例应用程序中&#xff0c;创建了一个名为OTV的新集群&#xff0c;并且在该集群的两个成员之间分配了一个名为user-map的缓存对象。 二手技术&#xff1a; JDK 1.6.…

JavaFX技巧来节省内存! 属性和可观察物的阴影场

在 JavaFX的世界中&#xff0c; Properties API允许UI开发人员将值绑定到UI控件。 这种功能非常容易&#xff0c;但是当对象模型经常使用属性时&#xff0c;应用程序可能会很快耗尽内存。 我通常会编写两个单独的对象&#xff0c;例如pojo类和表示模型对象。 此技术通常在基于S…

如何在Hibernate Search 5.5.2 / Apache Lucene 5.4.x中处理停用词?

停用词&#xff0c;例如[“ a”&#xff0c;“ an”&#xff0c;“ and”&#xff0c;“ are”&#xff0c;“ as”&#xff0c;“ at”&#xff0c;“ be”&#xff0c;“ but”&#xff0c;“ by”&#xff0c;“ for”&#xff0c;“ if”&#xff0c;“在”&#xff0c;“成…

Java----前端验证之验证码额实现

验证码是常用的登录验证方式之一,最大的作用就是保证安全,验证码的生成在java中实现的方式有很多种,比如后台生成传输到前端页面,在前台直接生成进行验证,下面写一个最简单实现验证码验证登录的例子. 生成验证码: 验证码验证逻辑: From表单登录: 没错,就这么的简单.在scripts生…

使用Spring Boot隔离集成测试和模拟依赖项

集成测试可能很慢且不可靠&#xff0c;因为它们依赖于系统中过多的组件。 在某种程度上&#xff0c;这是不可避免的&#xff1a;这里的集成测试是为了验证系统的每个部分如何与其他内部或外部组件一起玩。 但是&#xff0c;我们可以通过仅分解所需的依赖关系而不是整个系统来改…

Ubuntu 16.04下使用Wine安装Xshell 4和Xftp 4

说明&#xff1a; 1、使用的Wine版本是深度出品&#xff08;Deepin&#xff09;&#xff0c;已经精简了很多没用的配置&#xff0c;使启动能非常快&#xff0c;占用资源小。 2、由于Xshell 5的C库无法在这个Wine版本运行&#xff0c;即使升级官方原版的2版本也无法解决&#xf…

电脑缺失MSVCP110.dll文件

安装某软件显示如下错误。 错误&#xff1a; 原因&#xff1a;电脑缺少MSVCP110.dll系统文件。C:\Windows\System32目录下没有此文件。 解决&#xff1a; 下载vcredist_x64直接双击安装&#xff0c;安装完成后就可以继续安装之前安装不了的软件了。。 这里是我下载的&#…

在WildFly的REST Web服务中与Jackson的双向关系

这是使用Jackson的REST Web服务中Java实体之间的双向关系的示例。 假设我们在两个实体Parent和Child之间存在双向关系。 使用MySQL工作台为这两个表生成SQL模式文件。 DROP SCHEMA IF EXISTS bidirectional_schema ; CREATE SCHEMA IF NOT EXISTS bidirectional_schema DEFA…

Postman安装与使用(网络请求神器)--post、get请求

安装 1、Postman最早是作用chrome浏览器插件存在的&#xff0c;所以&#xff0c;你可以到chrome商店搜索下载安装&#xff0c;因为重所周知的原因&#xff0c;所以&#xff0c;大家都会找别人共享的postman插件文件来安装。由于2018年初Chrome停止对Chrome应用程序的支持。 官…