Java 8中的instanceof运算符和访客模式替换

我有一个梦想,不再需要操作员和垂头丧气的instanceof ,却没有访客模式的笨拙和冗长。 所以我想出了以下DSL语法:

Object msg = //...whenTypeOf(msg).is(Date.class).    then(date -> println(date.getTime())).is(String.class).  then(str -> println(str.length())).is(Number.class).  then(num -> println(num.intValue())).orElse(obj -> println("Unknown " + obj));

在Java 8中,没有向下转换,简洁的语法,强类型的……完全可以实现的。使用lambda和一些泛型,我创建了一个名为typeof的小型库 ,它比instanceofVisitor模式结合在一起是干净的,易于使用且更健壮的。 优势包括:

  • 没有明确的垂头丧气
  • 避免instanceof
  • 清洁且易于使用
  • 强类型
  • 适用于我们无法控制的类,包括JDK

这个小实用程序是出于Akka和Java API的目的而开发的,目的是限制instanceof运算符的使用,但它更通用。 同样,您可以根据运行时类型返回一些信息:

int result = whenTypeOf(obj).is(String.class).thenReturn(String::length).is(Date.class).thenReturn(d -> (int) d.getTime()).is(Number.class).thenReturn(Number::intValue).is(TimeZone.class).thenReturn(tz -> tz.getRawOffset() / 1000).is(MyType.class).thenReturn(7).get();

该库从上到下检查每个is()子句,如果找到包括父类在内的第一个匹配类,则停止运行,因此is(Number.class)将同时匹配IntegerFloat 。 如果没有条件匹配,则调用get将失败,并带有异常。 您可以使用orElse()重写此行为orElse()比等效的is(Object.class)更容易阅读):

int result = whenTypeOf(obj).is(String.class).thenReturn(String::length).//...orElse(42);

DSL利用Java中的静态类型的优势,几乎不可能错误地使用该库-大多数错误会在编译期间立即捕获。 以下所有代码段甚至都不会编译:

//ERROR - two subsequent is()
whenTypeOf(obj).is(Foo.class).is(Bar.class)//ERROR - then() without prior is()
whenTypeOf(obj).then(x -> println(x))//ERROR - mixing then() and thenReturn()
whenTypeOf(obj).is(Foo.class).then(foo -> println(foo)).is(Bar.class).thenReturn(bar -> bar.getB());

基本上,您首先输入whenTypeOf()Ctrl + space会准确告诉您允许的内容。 使用静态类型语言设计类型安全且健壮的DSL的关键是尽可能地限制API,以便在编译时避免无效的状态和调用。 您最终将获得大量的小类 ,但这没关系,您的用户将不会看到此内容。 例如,签出FirstIs.java –第一次调用is()之后返回的对象:

public class FirstIs<S, T> {final Then<S> parent;private final S object;private final Class<T> expectedType;public Then<S> then(Consumer<T> thenBlock) {if (matchingType()) {thenBlock.accept(castObject());return new TerminalThen<>();}return parent;}public <R> ThenReturn<S, R> thenReturn(Function<T, R> result) {if (matchingType()) {return new TerminalThenReturn<>(object, result.apply(castObject()));}return new ThenReturn<>(object);}public <R> ThenReturn<S, R> thenReturn(R result) {if (matchingType()) {return new TerminalThenReturn<>(object, result);}return new ThenReturn<>(object);}//...}

编写DSL比使用DSL困难得多,但最终还是很有收获的。 注意如何使用不同的返回类型( Then vs. ThenReturn )只是为了确保在每个阶段只能访问有效的方法。 另一种方法是实现运行时检查(例如,您不编写is(...).is(...).then(...) )–但是为什么还要麻烦编译器为我们做呢?

希望您喜欢本文,如果您愿意在项目中尝试使用此实用程序,请告诉我。 它可以在GitHub上获得 。

参考:来自Java和社区博客的JCG合作伙伴 Tomasz Nurkiewicz提供的Java 8中的instanceof运算符和访客模式替换 。

翻译自: https://www.javacodegeeks.com/2013/10/instanceof-operator-and-visitor-pattern-replacement-in-java-8.html

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

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

相关文章

1023 Have Fun with Numbers

因为最多有20个字符&#xff0c;int和long long都不行&#xff0c;所以只能用字符串操作。水题~ #include<iostream> #include<algorithm> #include<string.h> #define maxn 25 using namespace std; typedef long long ll; char s1[maxn]; int s2[maxn]; in…

前端生态混乱,AMPMIP在努力做标准化工作

作者 | Brilliant Open Web团队breezet 移动时代的前端似乎越来越混乱了&#xff0c;各种技术方案层出不穷&#xff0c;令开发者们目不暇接&#xff0c;不知如何选择。然而&#xff0c;生态越是混乱&#xff0c;对标准的呼唤就越强&#xff0c;因为只有标准化才能使得整个生态…

python逆向什么意思_如何理解python逆向切片

str 0123456789(推荐教程&#xff1a;python基础教程)如上,我们有一个数值型字符串,接下来我们分别从正向和逆向两个维度截取数据。str[start:end:step]start表示起始下标end表示结束下标step表示步长下面这个图,表示了正向和逆向下标的值首先我们要说一下方向的事情&#xff…

调试工具gdb

1.1 gdb符号调试器简介 gdb是一个用来调试C和C程序的功能强大的调试器&#xff0c;它能在程序运行时观察程序的内部结构和内存的使用情况。 gdb主要提供以下几种功能&#xff1a; 监视程序中变量值的变化设置断点&#xff0c;使程序在指定的代码行上暂停执行&#xff0c;便于观…

Apache Camel –从头开始开发应用程序(第1部分/第2部分)

开始之前 前一段时间&#xff0c;我写了一篇关于Spring Integration的教程&#xff0c;以演示如何在受现实发票处理系统启发的示例应用程序中使用Spring Integration。 我对此非常满意&#xff0c;因此我决定向您展示如何使用Apache Camel&#xff08;Spring Integration的最大…

Bourbon: 让你的sass更简洁

Bourbon是什么 bourbon是一个轻量级的Sass mixin和函数库&#xff0c;可以帮助我们快速开发样式. 官方文档 以下用webpack3.10.0( vue)为示例简述Bourbon的使用 安装配置 npm install bourbon -S 把bourbon添加到node-sass的includePaths中// webpack.config.js module.expor…

nat的地址映射 华为_华为PAT端口地址映射配置详解(一)

众所周知&#xff0c;PAT,&#xff0c;Port Address Translation&#xff0c;即网络地址转换。PAT有以下作用&#xff1a;1.改变数据包的ip地址和端口号&#xff1b;2.能够大量节约公网IP地址。PAT的类型有以下&#xff1a;1.动态PAT&#xff0c;包括NAPT和Easy IP&#xff1b;…

删除maven仓库中的lastUpdate文件

windows下打开命令行 进入maven本地仓库目录中 dos命令中执行下方命令.即可完成批量删除 for /r %i in (*.lastUpdated) do del %i 转载于:https://www.cnblogs.com/zlsxddgj/p/9324077.html

HDUOJ 1428

漫步校园 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5161 Accepted Submission(s): 1610 Problem DescriptionLL最近沉迷于AC不能自拔&#xff0c;每天寝室、机房两点一线。由于长时间坐在电脑边&#xff…

niosii spi 外部_基于Nios_II的DMA传输总结

最近练了一段时间的DMA传输&#xff0c;现做如下的总结&#xff0c;分享自己获得心得以及遇到的一些问题。在系统运行时&#xff0c;当需要传输大量数据时&#xff0c;可以采用DMA的方式进行传输&#xff0c;以解脱出CPU来处理其他命令。Nios II中的DMA传输有以下三种形式&…

杭州 GraphQLParty 第五场-GraphQL 基于 SPA 架构的工程实践文字版

本文为 2018 年 6 月 9 日&#xff0c;宋小菜与 Coding 共同举办的第一届 GraphQLParty &#xff0c;下午第五场国内某大型电商前端开发专家邓若奇的演讲稿&#xff0c;现场反响效果极好&#xff0c;对于想要尝试 GraphQL 和在公司初步实践的团队有很大的借鉴意义。 大家好&…

java反射机制基础总结

1反射机制是啥&#xff1f; 反射是运行中的程序检查自己和软件运行环境的能力&#xff0c;它可以根据它发现的进行改变。通俗的讲就是反射可以在运行时根据指定的类名获得类的信息。 2反射机制有啥用&#xff1f; Reflection(反射)是被视为动态语言的关键反射机制使程序在执行期…

使用sikuli和Arquillian测试HTML5 canvas应用程序

HTML5引入了一个很棒的新元素&#xff0c;可以用来在窗格上绘制任意内容&#xff1a; canvas元素。 数十年来&#xff0c;胖客户端应用程序的标准功能现已引入Web应用程序领域。 Web开发人员不再需要使用专有插件在其应用程序中绘制图像或图表。 但是&#xff0c;在进行测试时…

浅谈一下我了解的PWA

Progressive Web Apps,简称PWA&#xff0c;中文翻译过来就是渐进式网页应用&#xff0c;个人觉得它可以算是Web应用的下一个进化方向之一&#xff0c; 毕竟技术的发展有时候是不可预估的&#xff0c;谁也无法预料技术的走向&#xff0c;但至少它代表了一种可能性&#xff0c;下…

质性研究工具_质性研究【001】

袁长蓉 复旦大学 博士研究生导师课程 人类是追求意义的物种&#xff0c;会不断地从生活细节当中不断的归纳提炼&#xff0c;形成精神。形成理论抽象的概念&#xff0c;然后再利用这些概念&#xff0c;这些理论反过来&#xff0c;解释生活。 质性研究是由地到天的研究。质性研究…

python实现文件下载图片视频

最近在学习爬虫&#xff0c;在爬取网站时很多时候是需要将图片或视频下载到本地 今天就来说说如何使用urllib将图片保存到本地 以下代码均为win7 python3.6.* 方法一&#xff08;使用下载函数保存&#xff09; from urllib import request # 要下载的图片链接地址 img_url …

在JUnit中处理异常的3种方法。 选择哪一个?

在JUnit中&#xff0c;有3种流行的方式来处理测试代码中的异常&#xff1a; 尝试捕捉习语 使用JUnit规则 带注解 我们应该使用哪一个&#xff1f;何时使用&#xff1f; 尝试捕捉习语 这个习语是最受欢迎的习语之一&#xff0c;因为它已在JUnit 3中使用。 Testpublic void…

项目开发中发布更新文档备注

项目开发中 经常会遇到 某一个团队成员更新了,配置文件但是没有及时沟通导致项目发布后出现异常的情况。 这时就需要一个项目更新发布的规范说明文件,比如每次更新更改了哪些,进行文档备注。 更新的脚本文件也要随更新文档一起给到,配置文件也要将最新的配置信息给到。 转载于:…

bind函数polyfill源码解析

准备知识 使用new来调用函数会自动执行下面的操作&#xff1a; 创建一个全新的对象这个新对象会被执行原型连接这个新对象会绑定到函数调用的this如果函数没有返回其他对象&#xff0c;那么new表达式中的函数调用会自动返回这个新对象 注意this绑定规则&#xff0c;new操作具…

Java方法中的参数太多,第2部分:参数对象

在上一篇文章中 &#xff0c;我研究了与方法和构造函数的长参数列表相关的一些问题。 在那篇文章中&#xff0c;我讨论了用自定义类型替换基元和内置类型以提高可读性和类型安全性。 这种方法使方法或构造函数的众多参数更具可读性&#xff0c;但并没有减少参数的数量。 在本文…