提防Java中的函数式编程!

这对函数式编程并不会造成太大的影响,这真棒。 这是关于某些实践的警告,您很可能会将其应用于您的代码,而这完全是错误的!

高阶函数对于函数式编程是必不可少的,因此,谈论它们将帮助您成为聚会中的焦点。

如果您正在编写JavaScript,那么您就一直在这样做。 例如:

setTimeout(function() {alert('10 Seconds passed');
}, 10000);

上面的setTimeout()函数是一个高阶函数。 它是一个使用匿名函数作为参数的函数。 10秒钟后,它将调用作为参数传递的函数。

我们可以编写另一个简单的高阶函数来提供上述功能:

var message = function(text) {return function() {alert(text);}
};setTimeout(message('10 Seconds passed'), 10000);

如果执行上述操作,将执行message() ,并返回一个匿名函数,该函数将提醒您传递给message()的参数文本

在函数式编程中,以上是常见的做法。 从高阶函数返回的函数将捕获外部作用域,并在调用时能够对该作用域起作用。

为什么在Java中这种做法很危险?

出于同样的原因。 从高阶“函数”(方法)返回的“函数”(lambda)将捕获外部作用域,并在调用时能够对该作用域起作用。

这里给出了最简单的示例:

class Test {public static void main(String[] args) {Runnable runnable = runnable();runnable.run(); // Breakpoint here}static Runnable runnable() {return () -> {System.out.println("Hello");};}
}

在上述逻辑中,如果在执行runnable.run()调用的地方放置一个断点,则可以在堆栈上看到无害的lambda实例。 一个简单的生成类,支持功能接口的实现:

无害λ实例

现在,让我们将此示例转换为普通的Enterprise™应用程序(请注意注释 ),我们已对其进行了简化,以适合此博客文章:

class Test {public static void main(String[] args) {Runnable runnable = new EnterpriseBean().runnable();runnable.run(); // Breakpoint here}
}@ImportantDeclaration
@NoMoreXML({@CoolNewValidationStuff("Annotations"),@CoolNewValidationStuff("Rock")
})
class EnterpriseBean {Object[] enterpriseStateObject = new Object[100_000_000];Runnable runnable() {return () -> {System.out.println("Hello");};}
}

断点仍在同一位置。 我们在堆栈上看到了什么?

仍然是一个无害的小lambda实例:

无害lambda-instance-2

精细。 当然。 让我们添加一些其他日志记录,仅用于调试

class Test {public static void main(String[] args) {Runnable runnable = new EnterpriseBean().runnable();runnable.run(); // Breakpoint here}
}@ImportantDeclaration
@NoMoreXML({@CoolNewValidationStuff("Annotations"),@CoolNewValidationStuff("Rock")
})
class EnterpriseBean {Object[] enterpriseStateObject = new Object[100_000_000];Runnable runnable() {return () -> {// Some harmless debugging hereSystem.out.println("Hello from: " + this);};}
}

哎呀!

突然, this引用的“无害”之处迫使Java编译器将EnterpriseBean™的封闭实例包含在返回的Runnable类中:

危险的lambda与封闭的实例

随之而来的是沉重的enterpriseStateObject ,现在不再可以对其进行垃圾回收,直到调用站点释放无害的Runnable小对象为止。

好吧,这现在不是什么新鲜事了吗?

确实不是。 Java 8没有一流的功能,没关系。 通过名义上的SAM类型支持lambda表达式的想法非常狡猾,因为它允许升级和lambda-y-fy Java生态系统中的所有现有库,而无需对其进行更改。

而且,在匿名课堂上,整个故事也就不足为奇了。 自从旧的Swing 1.0样式好的ActionListener等以来,以下编码样式已通过匿名类泄漏了内部状态。

class Test {public static void main(String[] args) {Runnable runnable = new EnterpriseBean().runnable();runnable.run();}
}@ImportantDeclaration
@NoMoreXML({@CoolNewValidationStuff("Annotations"),@CoolNewValidationStuff("Rock")
})
class EnterpriseBean {Object[] enterpriseStateObject = new Object[100_000_000];Runnable runnable() {return new Runnable() {@Overridepublic void run() {System.out.println("Hello from " + this);}};}
}

什么是新的? lambda样式将鼓励在各处使用Java中的高阶函数。 这通常是好的。 但是只有当高阶函数是静态方法时,其结果类型才不会包含任何状态。

但是,通过以上示例,我们可以看到,在不久的将来,当我们开始接受Java 8的功能样式编程时,将通过一些内存泄漏和问题进行调试。

因此,请小心,并遵循以下规则:

(“纯”)高阶函数必须是Java中的静态方法!

进一步阅读

封闭实例之前已引起问题。 了解过去二十年来可怕的双花括号反模式如何在Java开发人员中造成痛苦。

翻译自: https://www.javacodegeeks.com/2015/11/beware-of-functional-programming-in-java.html

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

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

相关文章

LoadRunner脚本增强技巧之检查点

检查点的设置理解起来非常简单,就是要在服务器返回的页面中检查是否存在关键信息。检查点函数的错误会导致整个脚本运行结果的失败,通过这个功能可以方便地定位脚本运行中的逻辑错误。检查点的设置通常分为两种,一种是对文字的检查&#xff0…

苹果app商品定价_App Store 即将进行价格调整

当税率或外汇汇率变化时,我们有时需要更新 App Store 中的价格。即日起,巴基斯坦、哥伦比亚和台湾 App Store 中的产品价格(不包括自动续期订阅)将会上调。此次价格上调基于以下税率变化:• 哥伦比亚:自 2019 年 1 月 1 日起开始实…

es2016

对象解构 http://www.jb51.net/article/70140.htm 转载于:https://www.cnblogs.com/oneboi/p/7092847.html

hibernate 排序_Hibernate提示:排序和排序

hibernate 排序让我们介绍另一个Hibernate性能提示。 你还记得以前的Hibernate的模式后 ? 我们有一个与一对多协会有关的星际飞船和军官。 Entity public class Starship {Id GeneratedValue(strategyGenerationType.SEQUENCE) private Long id;public Long getId()…

苏宁大数据怎么运营_苏宁云商“三驾马车”:大数据、大物流、大金融并行

(赢商网1月15日报道)随着“未来的零售企业是线上线下的完美融合”这一趋势的走红,2013年年初苏宁电器决定更名为“苏宁云商”,而在更名之后,公司的转型步伐一直在不断加快,行动力也令业界为之刮目相看。“大物流”模式今日&#x…

VueJS组件之全局组件与局部组件

全局组件 所有实例都能用全局组件。 HTML <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title> <script src"https://cdn.bootcss.com/vue/2.2.2/vue.min.js&quo…

Spark简介,您的下一个REST Java框架

希望今年您对Java的热情很高&#xff01; 今天&#xff0c;我们将研究一个清新&#xff0c;简单&#xff0c;美观且实用的框架&#xff0c;以Java编写REST应用程序。 它将非常简单&#xff0c;甚至根本不会看起来像Java。 我们将研究Spark Web框架。 不&#xff0c;它与Apache…

jq的插件 vue中引用_详解如何在 vue 项目里正确地引用 jquery 和 jquery-ui的插件

本篇文章主要介绍了详解如何在 vue 项目里正确地引用 jquery 和 jquery-ui的插件&#xff0c;具有一定的参考价值&#xff0c;有兴趣的可以了解一下使用vue-cli构建的vue项目&#xff0c;webpack的配置文件是分散在很多地方的&#xff0c;而我们需要修改的是build/webpack.base…

SQL Search

Press TAB to expand wildcard tab键之后&#xff0c;会自动展开&#xff0c;直接枚举表中所有的字段 根据名字查找存储过程&#xff0c;发现找不到 原因是&#xff0c;本地是一个备份库。服务器上通过sql source control进行版本控制的。 在通过sql source control将服务器上新…

Java日期工具类

Java日期工具类对日期格式进行转化&#xff0c;例如&#xff0c;将2018-12-13转化成20181213&#xff0c;也可以反过来。 package main.java.utils;import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date;public class DateUtil {/*** …

两个数组合成一个json对象_两个jsonarray合并

技术文档主体内容&#xff1a;可以认为是页面最想表达的内容总和。对于内容详情页来说&#xff0c;主体内容指从标题开始至正文内容结束&#xff0c;翻页区域也被视为主体内容&#xff0c;文章后的评论、分享、推荐等不视为主体内容。首屏&#xff1a;用户点击搜索结果后进入移…

04_传智播客iOS视频教程_类是以Class对象存储在代码段

1231312转载于:https://www.cnblogs.com/ZHONGZHENHUA/p/7097077.html

drools的guvnor_Drools Guvnor –管理访问

drools的guvnor外部化业务或技术规则对于可伸缩应用程序非常重要&#xff0c;但是应该管理BRMS服务访问。 guvnor使用基于角色的授权提供控件UI访问和操作。 在drools-guvnor参考手册中列出了几种权限类型。 具有所有权限的管理员。 分析师或只读分析师&#xff1a;特定类别的分…

安卓实现序列化之Parcelable接口

安卓实现序列化之Parcelable接口 1.实现序列化的方法&#xff1a; Android中实现序列化有两个选择&#xff1a;一是实现Serializable接口&#xff08;是JavaSE本身就支持的&#xff09; 。一是实现Parcelable接口&#xff08;是Android特有功能&#xff0c;效率比实现Serializa…

容器对象模式。 一种新的测试模式。

如果您搜索什么是页面对象的描述&#xff0c;就会发现页面对象模式为我们提供了一种以可重用和可维护的方式对内容建模的常识方法。 还要指出&#xff1a;在Web应用程序的UI中&#xff0c;您的测试与某些区域交互。 Page Object只是将它们建模为测试代码中的对象。 这减少了重…

字符串工具类,随机生成字符串

字符串工具类&#xff0c;随机生成字符串package main.java.utils;import java.util.Map; import java.util.Random;public class StrUtil {/*** 定义一个字符串&#xff08;A-Z&#xff0c;a-z&#xff09;*/private static final String STR_ONE "abcdefghijklmnopqrs…

css与网页制作

百度&#xff1a;常用DIVCSS命名大全集合转载于:https://www.cnblogs.com/Tpf386/p/7100017.html

Oracle修改密码文件_转载:Oracle修改用户密码

转载一位大佬的博文&#xff0c;用于帮助常忘记密码的我和某些同道。1. 通过系统管理员(system)修改密码修改普通用户密码相对来说简单很多。1.1 登录系统管理员账户。一般为system。1.2 查询当前系统存在的用户。这一步属于辅助性查找&#xff0c;可以不执行。select username…

爬虫突破IP封锁

爬虫突破IP封锁 爬取网站最常出现的问题就是IP封锁的问题,较为简单的方法就是购买有效IP,免费IP虽然不花钱,但是不好用,做爬取测试的时候还勉强能用。 我从快代理购买付费的IP,把自己的电脑的IP加入白名单,再使用其提供的Api获取有效IP进行爬取。 package com.zhq.crawle…

Python异常处理和进程线程

写在前面 最坏的结果&#xff0c;不过是大器晚成&#xff1b; 一、异常处理 - 1.语法错误导致的异常 - 这种错误&#xff0c;根本过不了python解释器的语法检测&#xff0c;必须在程序运行前就修正&#xff1b; - 2.逻辑上的异常 - 即逻辑错误&#xff0c;例如除零错误&#xf…