鸭子在Java中打字? 好吧,不完全是

根据维基百科,鸭子的打字是:

动态类型的类型,其中对象的方法和属性确定有效的语义,而不是其从特定类或特定接口的实现继承

用简单的话

当我看到一只鸟走路像鸭子,游泳像鸭子,嘎嘎像鸭子一样时,我称那只鸟为鸭子

在具有动态类型的语言中,此功能允许创建的功能不检查传递的对象的类型,而是依赖于其中存在的特定方法/属性,并在找不到这些属性时抛出运行时异常。 例如,在groovy中,我们可以使用一种方法来打印有关某个实体的信息

def printEntity = {entity ->println 'id: ${entity.id}, name: ${entity.name}' 
}

假设我们有以下课程

class Entity {Long idString name
}

这样我们就可以调用我们的函数

printEntity(new Entity(id: 10L, name: 'MyName1'))
id: 10, name: MyName1

但是同时我们可以将map作为参数传递

printEntity(['id':10L, 'name':'MyName2'])
id: 10, name: MyName2

使用一些元编程魔术,我们甚至可以编写以下内容

class Ghost {def propertyMissing(String name) {if (name == 'id') {return -1L} else if (name == 'name') {return 'StubName'}}
}

而且我们仍然可以调用我们的函数

printEntity(new Ghost())
id: -1, name: StubName

欢迎来到真实的世界

幸运的是,这个概念不仅可以用于具有动态类型的语言,而且可以用于具有更严格类型模型的语言,例如Java。 Wikipedia很好地说明了使用Proxy类在Java中进行鸭子输入的实现。

好吧,你说,除了让自己成为最聪明的专家以外,这的实际用途是什么:)让我展示一些使用鸭子类型技术在Java中解决的现实生活任务。

从一开始,我就拥有一个简单的报表生成器,该报表生成器查询产品的数据库并输出某些实体的ID和名称。 但随后客户说:“我还想链接到我们网站上的实体详细信息页面。 美丽的SEO友好链接。 你能对我做吗? “当然”,我说。 深入研究我们的代码库后,我发现很酷的函数generateSeoUrl()可以完成这项工作。 该函数采用Entity类型的一个参数,即interface。 因此,我的目的是观察Entity的实现,并尝试使用其中之一进行报告生成。 当我发现它们全部都是某些自制的ORM工具的一部分并且他们的构造函数接受查询DB以获取有关产品的全部信息后,我感到非常惊讶。

因此,如果我使用的是Entity实现,则必须在报表的每一行中处理一个额外的查询,这是不可接受的,因为报表由大量的行组成。 因此,我决定尝试其他方法并实现Entity接口,该方法覆盖了generateSeoUrl()使用的方法。 我单击了IDE快捷方式,再次感到惊讶。 实体有大约50(!!!)个方法。 好吧,我已经知道generateSeoUrl()函数仅使用getEntityId()和getName(),但是再说一次,使用具有50个空方法的新类来覆盖其中的2个做有用的动作对我来说不是一个好主意。

因此,我决定停止尝试编码,并开始思考:)扩展某些Entity实现以防止查询数据库或复制+粘贴generateSeoUrl()并根据我的需要采用它,但是这些选择仍然很漂亮。 特别是当我提醒鸭子打字时。 我对自己说,我们有一个采用Entity实例但仅使用此接口的两种方法的函数,因此要完成我的任务,我需要看起来像Entity并能够处理getEntityId()和getName()方法的东西。

由于实体ID和名称已经存在于用于生成报告的数据中,因此我可以在新类中重用它们以对getEntityId()和getName()的数据进行存根。 为了实现鸭子类型,我们需要创建Proxy,该Proxy还实现InvocationHandler接口和静态方法来检索Proxy实例。 我班的最终代码看起来像

public class ReportEntitySupport implements InvocationHandler {public static Entity newInstance(Long entityId, String name) {return (Entity) Proxy.newProxyInstance(Product.class.getClassLoader(),Product.class.getInterfaces(),new ReportEntitySupport(entityId, name));}private final String name;private final Long entityId;private ReportEntitySupport(Long entityId, String name) {this.name = name;this.entityId = entityId;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getName().equals('getName')) {return this.name;} else if (method.getName().equals('getEntityId')) {return this.entityId;}return null;}
}

那么如何使用呢?

在我的报表生成器类中,同时遍历ResultSet时,我正在使用以下代码

Long entityId;
String name;
....
Entity entity = ReportEntitySupport.newIntance(entityId, name);
String seoUrl = generateSeoUrl(entity);
....

聚苯乙烯

这篇文章仅说明了一些不常见的Java语言概念可以成功地用于完成现实生活中的任务,从而提高您的编程技能并使代码更漂亮。

参考: 鸭子在Java中打字? 嗯,这不完全是我们JCG合作伙伴 Evgeny Shepelyuk在jk的博客博客上获得的。


翻译自: https://www.javacodegeeks.com/2012/09/duck-typing-in-java-well-not-exactly.html

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

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

相关文章

前端学习路线

第一部分 HTML 第一章 职业规划和前景 职业方向规划定位: web前端开发工程师 web网站架构师 自己创业 转岗管理或其他 web前端开发的前景展望: 未来IT行业企业需求最多的人才 结合最新的html5抢占移动端的市场 自己创业做老板 随着互联网的普及we…

p1164【立方体求和】

题目: SubRaY有一天得到一块西瓜,是长方体形的....SubRaY发现这块西瓜长m厘米,宽n厘米,高h厘米.他发现如果把这块西瓜平均地分成m*n*h块1立方厘米的小正方体,那么每一小块都会有一个营养值(可能为负,因为西瓜是有可能坏掉的,但是绝对值不超过200).现在SubRaY决定从这…

html生成自定义表格,自定义js的表格插件

场景:指定元素,生成自定义表格。目的:了解js的插件开发。html代码:自定义表格插件var test new MyTable({elid:"mytable",//定义哪个div要生成表单thead:{//指定列名name:"姓名",age:"年龄",addr:…

使用JBehave,Gradle和Jenkins的行为驱动开发(BDD)

行为驱动开发 (BDD)是一个协作过程 ,产品负责人,开发人员和测试人员可以合作交付可为企业带来价值的软件。 BDD是 测试驱动开发 (TDD) 的合理下一步 。 行为驱动的发展 本质上,BDD是一种交付…

手型显示html,css各种手型集合(css禁止手型)

html>css各种手型集合(css禁止手型).auto { cursor: auto; }.deafult { cursor: default; }.none { cursor: none; }.context-menu { cursor: context-menu; }.help { cursor: help; }.pointer { cursor: pointer; }.p…

Maven Fluido Skin和Javadoc类图

我使用Maven网站已有一段时间了,对此我感到非常满意。 我不想在Maven 3之后更新我的项目,但是没关系,Maven 3带来了许多新奇的东西。 但是,有两件事使我感到烦恼:缺乏美观和现代的外观,以及浏览复杂代码的J…

ZooKeeper安装,部署

实验环境 192.168.1.10  Zookeeper1:2181, Zookeeper2:2182 192.168.1.11  ZooKeeper3:2181 依赖环境 JDK1.7 安装,配置 1、下载解压 # 192.168.1.10cd /data/server tar -zxv -f zookeeper-3.4.6.tar.gz ln -s zookeeper-3.4.6 zookeeper1ln -s zookeeper-3.4.…

咸宁省2021年模拟高考成绩查询怎么查,2021咸宁市地区高考成绩排名查询,咸宁市高考各高中成绩喜报榜单...

距离2018年高考还有不到一个月的时间了,很多人在准备最后冲刺的同时,也在关心高考成绩。2018各地区高考成绩排名查询,高考各高中成绩喜报榜单尚未公布,下面是往年各地区高考成绩排名查询,高考各高中成绩喜报榜单,想要了解同学可以…

保证主题,JMS规范和ActiveMQ的消息传递

最近,一个客户要求我仔细研究ActiveMQ的“持久”消息的实现,它如何应用于主题以及在存在非持久订阅者的故障转移方案中会发生什么。 我已经了解到,JMS语义规定,即使面对消息代理提供者失败,也只能保证主题的持久订户以…

java中的除法及求余运算特殊性。

1.如果除法运算符的两个操作数都是整数类型,则计算结果也是整数,就是将自然除法的结果截断取整,例如19/4的结果是4,而不是5。并且除数不能0,否则将引起除0异常 2.如果运算符的两个操作数有1个是浮点数,或两…

林海峰老师python课件密码

egon4573转载于:https://www.cnblogs.com/fengjunhua/p/7395591.html

国际旅游管理专业跨专业考计算机,旅游管理考研我想跨专业考旅游管理专业的研究 – 手机爱问...

2005-12-11我是学旅游管理的大一学生,听人说这专业就这位兄弟提出的苦恼在大学生中很典型呀!其实你说的不尽然!旅游管理专业,是个很有前景的专业呀!怎么会没有前途呀?你对自己的人生也太悲观了吧?就是你说,学校不太好,这可能对自身在大学四年的发展有所限制,但这主要还是看自…

Java注释:探究和解释

Java 5 SE的许多出色功能之一是Annotations构造的引入。 注释是一些标签,我们可以将其插入程序源代码中,以使用某种工具对其进行处理并使其变得有意义。 注释处理工具通常使用(Java 5 SE的)Reflection API在Java代码或字节码级别的…

C# 类

一 string 类型 变量.Length - 字符串长度,返回int类型 string s "abcdefg"; int a s . Length; Console.WriteLine(a); // 输出结果为:7(此字符串有7个字符) // Length返回有多少个字符&am…

node+mongodb+win7

一、安装mongodb,参照教程,注意要先启动mongod.exe,再启动mongd.exe。 转载于:https://www.cnblogs.com/iloveyou-sky/p/7396997.html

cdrom是多媒体微型计算机,全国计算机二级题库第三章

同时按下CTRLALTDEL组合键的作用是(使用任务管理器关闭不响应的应用程序下列说法正确的是(在微型机性能指标中,CPU的主频越离,其运算速度越快)微型计算机键盘上的Tab键是(交替换档键)微型计算机键盘上的Enter键是(回车键)微型计算机的运行速度的单位是mi…

Spring MVC控制器JUnit测试

JUnit测试Spring MVC控制器并非易事 。 但是最近,一个新项目 (即将在Spring推出)提供了新工具来简化此工作。 这篇文章说明了如何通过JUnit测试来测试一个简单的控制器。 该代码是JUnit Testing Spring Service和DAO(带有内存数据…

java基础03变量和基本数据类型

package cn.bdqn.test;/*** * author 小豆腐* * 变量:会变化的量??* 一个数据在内存中存储空间的表示!在运行期间可以动态改变!* * 关键字:在java中已经被使用或者定义的单词!不能作为变量名&#xff01…

5.set集合

list_1 [1,2,3,4,5]list_2 [1,3,5,7,9]#列表转成set集合set_1 set(list_1)set_2 set(list_2)#交集print(set_1.intersection(set_2))print(set_1 & set_2)#判断没有交集print(set(["a","b"]).isdisjoint(set_1))#并集print(set_1.union(set_2))pri…

JavaFX中基于表达式的PathTransitions

在JavaFX中,您可以使用PathTransition对象为路径上的节点设置动画。 PathTransitions使用Shape对象描述它们需要沿其动画的路径。 JavaFX提供了各种类型的形状(例如,多边形,圆形,多边形,路径)。…