会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接口,该方法覆盖了generateSeoUrl()使用的方法。 我单击我的IDE快捷方式,再次感到惊讶。 实体有大约50(!!!)个方法。 好吧,我已经知道generateSeoUrl()函数只使用getEntityId()和getName(),但是再说一次,使用具有50个空方法的新类来覆盖其中的2个做有用的动作对我来说不是一个好主意。

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

由于EntityId和name已经存在于用于生成报告的数据中,因此我可以在新类中重用它们以对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

会java的鸭子

会java的鸭子_鸭子在Java中打字? 好吧,不完全是相关推荐

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

    根据维基百科,鸭子的打字是: 动态类型的类型,其中对象的方法和属性确定有效的语义,而不是其从特定类或特定接口的实现继承 用简单的话 当我看到一只鸟走路像鸭子,游泳像鸭子,嘎嘎像鸭子一样时,我称那只鸟为 ...

  2. 马士兵 java 学习笔记_马士兵java教程笔记1

    ---恢复内容开始--- 前记 虽然已经是个研究生了,但是会的东西还是特别的少 甚至连java都不能说是很会 所以准备从现在开始能好好的学习java 变成java master 标识符 标识符是由字母 ...

  3. 怎样下载java知乎_怎样下载JAVA?

    Java 开发环境配置 在本回答中我们将为大家介绍如何搭建Java开发环境.Windows 上安装开发环境 Linux 上安装开发环境 安装 Eclipse 运行 Java window系统安装jav ...

  4. java 02-cf_cf活动如何设置java环境变量_如何设置java环境变量

    cf助手怎么连接wifi_连接无线网设置 对于刚刚学习java的win7用户来说,首先要学会安装jdk和配置java环境变量,这是学习java的唯一途径,否则编写的代码运行时会出现bug.关于这一点, ...

  5. java 字符串乱码_这份Java面试题含答案解析竟然真的让你不用在面试上“如履薄冰”...

    面试题集共分为以下十部分: 一.Core Java: 1 - 95 题1 - 24 页 基础及语法: 1 - 61 题1 - 13 页 异常: 62 - 69 题13 - 15 页 集合: 70 - ...

  6. java console 交互_实例讲解java中Console类的用法

    java的Console类的使用方法及实例 java的Console类的使用方法及实例 JDK 6中提供了java.io.Console类专用来访问基于字符的控制台设备.如果你的Java程序要与Win ...

  7. java for循环_愉快地学Java语言:第五章 循环

    导读 本文适合Java入门,不太适合Java中高级软件工程师.本文以<Java程序设计基础篇>第10版为蓝本,采用不断提出问题,然后解答问题的方式来讲述.本篇文章只是这个系列中的一篇,如果 ...

  8. java 内存空间_怎样用java实现存储空间动态分配

    1.java是如何管理内存的 Java的内存管理就是对象的分配和释放问题.(两部分) 分配 :内存的分配是由程序完成的,程序员需要通过关键字new 为每个对象申请内存空间 (基本类型除外),所有的对象 ...

  9. linux java远程调试_[转]JPDA:Java平台调试架构(常用的远程调试方法)

    原文出处:http://www.javaeye.com/topic/75128 最近使用WTP的Server功能很不爽,连tomcat服务器时java类中的任何改动都要重启服务器,一怒之下就改用JPD ...

最新文章

  1. opencv和python的区别_所有这些OpenCV Python接口之间有何不同?
  2. day01-计算机操作系统java编程入门
  3. SAP Analytics Cloud里的Smart Predict
  4. 前后端交互中,返回前端的自定义响应数据结构
  5. 【ArcGIS微课1000例】0015:ArcGIS如何创建/自定义快捷键?
  6. 可定制的PHP缩略图生成程式(需要GD库支持)
  7. 冷热分离和直接使用大数据库_「系统架构」如何通过分离冷热数据提升系统性能?...
  8. 计算机系统-电路设计10-寄存器的内部电路实现(输入与输出不同线)
  9. 拓扑排序那点事(vector+priority_queue)
  10. kaggle房价预测特征意思_未来销量预测——Kaggle基础方案(三):特征工程及线下验证划分...
  11. 风力摆控制系统2015年全国大学生电子设计竞赛B题
  12. 计算机网络-----网络编程
  13. 一篇文章了解光学器件的各种参数含义
  14. 看图和步骤教你把dwg转换成pdf格式
  15. IDEA默认KeyMap映射快捷键
  16. 1982年图灵奖--斯蒂芬·库克简介
  17. CAD二开之打开时插件命令自动加载(RibbonUI自动显示)
  18. uniapp 微信小程序 map获取接口数据后地图标注marker不会渲染显示
  19. 什么是平台架构?平台架构的用处有哪些?
  20. 第十讲:Python爬取网页图片并保存到本地,包含次层页面

热门文章

  1. Jsoup代码解读之四-parser(上)
  2. Java多线程sleep和wait的区别,总结得非常好
  3. hexo部署在码云出现样式问题
  4. Java GUI界面
  5. 用IDEA把SpringBoot项目打成jar发布项目 不要用 在上面有可以用的
  6. mysql切换用户sql语句,MySQL用户管理及SQL语句详解
  7. 如何彻底删除MySQL数据库(保姆级教学)
  8. datatable中某一列最小值_获取DataTable 某一列所有值
  9. http响应状态码列表
  10. tomcat(supplement)HttpConnector.initialize() 和 start() 方法 以及 StandardContext.start()方法的分析