java 范式 问号_冒号和他的学生们(连载9)——泛型范式
算法是脊,数据是肉;思想是鸡,结论是蛋——题记
冒号重新开讲:“你们会不会经常遇到这种情景:一遍又一遍地写着相似的代码,有心将其归并,却因种种原因无法践行。”
逗号心有戚戚焉道:“是啊,有时明明两个函数的实现几乎一模一样的,就因为某些参数不匹配,无法合而为一。”
“有一种编程范式可以解决这个问题,它打破了不同数据结构之间的壁垒,让你的代码不再臃肿,这——就是泛型编程。”冒号的语调和说辞不免令人联想到电视上的减肥广告,“Generic Programming,简称GP,其基本思想是:将算法与其作用的数据结构分离,并将后者尽可能泛化,最大限度地实现算法重用。这种泛化是基于模板的参数多态(parametric polymorphism),相比OOP基于继承的子类型多态(subtype polymorphism),不仅普适性更强,而且效率也更高。这不能不说是一种异数——我们知道,普适性往往是以效率为代价的。GP最著名的代表是C++中的STL,其后亦为Java,C#等所吸纳。此外,一些函数式语言如Ocaml、Standard ML、Generic Haskell等也支持GP。”
冒号写下两段代码——
C++(泛型编程):
template
T max(T a, T b) //求出两个数中的较大者
{
return (a > b) ? a : b;
}
C(宏定义):
#define max(a,b) ((a) > (b) ? (a) : (b))
“求两个数中的较大值是经常遇到的问题。”冒号解说着,“对于静态类型语言来说,若参数类型不同,即使函数体相同也不能合为一体。如果语言不支持重载(overload),还可能出现maxInt、maxLong、maxFloat、 maxDouble之类的函数名,冗赘而丑陋。尽管在C中可用宏定义来实现,但无法保证类型安全,而C++模板则兼顾类型安全和代码重用,并且由于是在编译期间展开的,效率上也不损失。不止于此,C++支持运算符重载,除数值类型外,一切定义了‘>’ 运算的数据类型均可调用max函数,真是一举N得,N趋向无穷大啊!”
冒号边说边比划,夸张的语气和手势逗得大家都笑了。
引号提出疑问:“Java的一切对象都是Object,将所有参数都换成Object类型,岂不也是一种泛化?”
冒号答道:“首先,基本类型如int,float等不是Object的子类,虽然Java 新增了自动装拆箱(autoboxing/unboxing)的功能,但要付出性能的代价。更重要的是,这将不可避免地需要类型强制转换,丧失了静态类型语言的优势,为Bug大开方便之门。这也是Java最终引入模板的原因,虽然有些姗姗来迟。类似地,C/C++中的通用指针void *也有类型安全问题。”
句号发表他的看法:“泛型虽好,似乎只是某些局部才用到的技术,不具有前面几种范式的渗透性。”
冒号听罢不语,返身在黑板上写下几道题——
1.从一个整数数组中随机抽取十个数,对其中的素数求和
2.将一个无序整数集中所有的完全平方数换成其平方根
3.从学生成绩表中,列出门门都及格且平均分在70分以上的学生名单
4.在一个着色二元树中,将所有的红色结点涂成蓝色
5.将一个字符串从倒数第三个字符开始反向拷贝到另一个字符串中
6.每从标准输入读取一个非数字的字符,于标准输出打印‘请输入数字’
句号暗忖,不过是些常规题嘛。不料冒号的问题却出人意表:“请问它们之间有何共同之处?能否共享一段代码?”
见众人缄默已久,冒号接着投影出一段代码——
template
void process(Iterator begin, Iterator end, Act act, Test test)
//对容器中在给定范围内(即起于begin止于end)所有满足给定条件的元
//素(即test(元素)==true)进行处理(即act(元素))
{
for ( ; begin != end; ++begin) //从头至尾遍历容器内元素
if (test(*begin)) act(*begin); //若当前元素满足条件,则对其采取行动
}
“STL有三要素:算法(algorithm)、容器(container)和迭代器(iterator)。容器是数据的集合,可理解为抽象的数组;迭代器是算法与容器之间的接口,可理解为抽象的指针或者游标。”冒号讲述道,“算法串联数据,如脊贯肉;数据实化算法,如肉附脊。只有抽象出表面的数据,算法的脊梁才能显现。以上几题看似风马牛不相及,若运用泛型思维,便可发现它们的共性:对指定集合中满足指定条件的元素进行指定处理。用模板语言,寥寥数行即勾勒完毕。”
问号诧异道:“相比前面的max模板,这里连元素的数据类型T都不见了?”
冒号回答:“元素被容器封装了。”
问号追问:“可这里连容器也看不到啊?”
冒号料有此问:“容器通过它的迭代器参与算法。”
句号豁然开朗:“通过模板,泛化了容器——可以是数组、列表、集合、映射、队列、栈、字符串等等;泛化了元素——可以是任何数据类型;泛化了处理方法和限定条件——可以是任何函数。”
冒号提醒道:“补充两点:处理方法和限定条件不限于函数,还可以是函子(Functor)——自带状态的函数对象;另外还有一个隐蔽的泛化:迭代器——可以从前往后移动,可以从后往前移动,可以随机移动,也可以按任意预先定义的规律移动。”
叹号由衷感叹:“果然强悍啊!”
逗号倒也心细:“最后一题中标准输入也算容器吗?”
“为什么不呢?只要一个对象配备了迭代器,它就算容器。I/O流上就有现成的迭代器,当然你也可以自行定制。”冒号目光转向句号,“现在还有人说泛型编程渗透性不强吗?”
句号腆然一笑。
“这只是泛型编程的冰山一角。重要的是,我们不是在玩弄花哨的技巧,而是在用一种新的视角去审视问题。”冒号总结道,“泛型编程是算法导向(Algorithm-Oriented)的,即以算法为起点和中心点,逐渐将其所涉及的数据结构内涵模糊化、外延扩大化,从而扩展算法的适用范围。这非常类似数学思维——当数学家证明完一个定理后,总会试图在保持核心思想的前提下,尽可能地放宽题设,增强结论,从而推广定理。外行人以为数学定理最重要,其实数学思想才是数学的精髓,在数学家眼里,思想是鸡,结论是蛋。这也无怪乎STL会出自一位学数学的人之手了。”
java 范式 问号_冒号和他的学生们(连载9)——泛型范式相关推荐
- java 范式 问号_巴科斯范式和扩展巴科斯范式
巴科斯范式(也称为巴科斯-瑙尔范式.巴克斯-诺尔范式)即 BNF 是一种用于表示上下文无关文法的语言,上下文无关文法描述了一类形式语言.尽管巴科斯范式也能表示一部分自然语言的语法,它还是更广泛地使用于 ...
- studentname在java中怎么_是教师,还是学生?setName法和string赋值法区别在哪里!!!...
[java]代码库import java.util.ArrayList; import java.util.List; //主函数 public class ArrayListDemo { publi ...
- Java何为范式_冒号课堂§3.1:泛型范式
冒号课堂 第三课 常用范式(1) 课前导读 这一课介绍了四个常用的编程范式:泛型式.元编程.切面式和事件驱动式. 本课共分四节-- 1.泛型范式 2.超级范式 3.切面范式 4.事件驱动 3.1泛型范 ...
- java 语法 冒号_冒号课堂 - 冒号专栏 - BlogJava
冒号课堂 新版<冒号和他的学生们> 抽象类型--实中之虚(介绍抽象类型的种类.意义及其用法) •浅显的比方只是门槛前的台阶,借之或可拾级入门,却无法登堂入室 •具体类型是创建对象的模板,抽 ...
- java中的双冒号操作符
java :: Java中的双冒号操作符 </h1><div class="clear"></div><div class="p ...
- 《冒号课堂》连载之七——声明范式:目标决定行动
<冒号课堂>连载之七--声明范式:目标决定行动 2.2 声明范式--目标决定行动 给我一个支点,我能挪动地球. --阿基米德 关键词:编程范式:命令式编程:声明式编程:函数式编程:逻辑式 ...
- 逗号表达式 java_c和java中问号表达式与逗号表达式问题
C语言中的问号表达式. --?--:-- 式A?B:C值为:若A为真,则B:若A为假,则C. 但有一点是值得注意的,那就是问号表达式的结合性,问号表达式是从右往左的运算方向 尤其是当问号表达式嵌套使用 ...
- JVM - 结合代码示例彻底搞懂Java内存区域_对象在堆-栈-方法区(元空间)之间的关系
文章目录 Pre 示例demo 总体关系 代码示例论证 反汇编 Pre JVM - 结合代码示例彻底搞懂Java内存区域_线程栈 | 本地方法栈 | 程序计数器 中我们探讨了线程栈中的内部结构 ,大家 ...
- Java计算时间差_传统的SimpleDateFormat类
Java计算时间差_传统的SimpleDateFormat类 SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd ...
最新文章
- DeepMind 的新强化学习系统是迈向通用 AI 的一步吗?
- python csv读取-使用python获取csv文本的某行或某列数据的实例
- 你知道钓鱼网站的形成步骤吗?一次网络钓鱼演练带你了解(增强安全意识)
- hibernate报错 net.sf.json.util.CycleDetectionStrategy$StrictionStrategyRepeatedReferenceAsObject
- 电竞人才平均月薪感受下!上海薪资领跑全国
- ubuntu apt 卸载 golang
- 边界值法中的上点、内点和离点分析
- hdu6287 口算训练
- Spring MVC 详解
- 细思极恐!大数据和机器学习揭示十二星座的真实面目
- 安卓版matlab下载,matlab转为app
- js 数字金额的转换 (转)
- 解析 通证经济的分类及用途
- MySQL安装版本Navicat连接报错2509解决方案
- HDU-5761-Rower Bo(微分方程)
- accept文件上传类型
- 双非南京大学计算机夏令营,一名双非生的“失败”保研经历:夏令营不确定是否有保研资格,预推免上岸理想院校!...
- 计算机用用技巧,计算机使用技巧介绍汇总
- 计算机加密恢复,系统小技巧:BitLocker密钥恢复二三事
- TDSQL-C 真·秒级启停:连接断了,又没断
热门文章
- linux列表中添加多个元素,这12种方法轻松合并Python中的列表
- 第一篇第一章燃烧的基础知识
- alfresco 忘记admin密码
- 基于AUTOSAR开发工具链的AUTOSAR软件实战开发-软件架构设计(二)
- 高中英语怎样学好呀,负基础
- 保研计算机英语词汇,保研英语面试离不开的几个话题,回答都给你整理好了
- 初学绘画怎么去注意头发的高光和阴影?如何才能画好高光和阴影?
- 华为电脑linux装win7不用u盘,华为笔记本开不了机 怎么用u盘安装windows7
- 读书笔记——阿里数据中台(第二篇:OneData体系1)
- CSS3地图动态实例(圆圈向外扩散)