日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

提防Java中的函数式编程!

發(fā)布時(shí)間:2023/12/3 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 提防Java中的函数式编程! 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這對函數(shù)式編程并不會造成太大的影響,這真棒。 這是關(guān)于某些實(shí)踐的警告,您很可能會將其應(yīng)用于您的代碼,而這完全是錯(cuò)誤的!

高階函數(shù)對于函數(shù)式編程是必不可少的,因此,談?wù)撍鼈儗椭蔀榫蹠械慕裹c(diǎn)。

如果您正在編寫JavaScript,那么您就一直在這樣做。 例如:

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

上面的setTimeout()函數(shù)是一個(gè)高階函數(shù)。 它是一個(gè)使用匿名函數(shù)作為參數(shù)的函數(shù)。 10秒鐘后,它將調(diào)用作為參數(shù)傳遞的函數(shù)。

我們可以編寫另一個(gè)簡單的高階函數(shù)來提供上述功能:

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

如果執(zhí)行上述操作,將執(zhí)行message() ,并返回一個(gè)匿名函數(shù),該函數(shù)將提醒您傳遞給message()的參數(shù)文本

在函數(shù)式編程中,以上是常見的做法。 從高階函數(shù)返回的函數(shù)將捕獲外部作用域,并在調(diào)用時(shí)能夠?qū)υ撟饔糜蚱鹱饔谩?

為什么在Java中這種做法很危險(xiǎn)?

出于同樣的原因。 從高階“函數(shù)”(方法)返回的“函數(shù)”(lambda)將捕獲外部作用域,并在調(diào)用時(shí)能夠?qū)υ撟饔糜蚱鹱饔谩?

這里給出了最簡單的示例:

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

在上述邏輯中,如果在執(zhí)行runnable.run()調(diào)用的地方放置一個(gè)斷點(diǎn),則可以在堆棧上看到無害的lambda實(shí)例。 一個(gè)簡單的生成類,支持功能接口的實(shí)現(xiàn):

現(xiàn)在,讓我們將此示例轉(zhuǎn)換為普通的Enterprise?應(yīng)用程序(請注意注釋 ),我們已對其進(jìn)行了簡化,以適合此博客文章:

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");};} }

斷點(diǎn)仍在同一位置。 我們在堆棧上看到了什么?

仍然是一個(gè)無害的小lambda實(shí)例:

精細(xì)。 當(dāng)然。 讓我們添加一些其他日志記錄,僅用于調(diào)試

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?的封閉實(shí)例包含在返回的Runnable類中:

隨之而來的是沉重的enterpriseStateObject ,現(xiàn)在不再可以對其進(jìn)行垃圾回收,直到調(diào)用站點(diǎn)釋放無害的Runnable小對象為止。

好吧,這現(xiàn)在不是什么新鮮事了嗎?

確實(shí)不是。 Java 8沒有一流的功能,沒關(guān)系。 通過名義上的SAM類型支持lambda表達(dá)式的想法非常狡猾,因?yàn)樗试S升級和lambda-y-fy Java生態(tài)系統(tǒng)中的所有現(xiàn)有庫,而無需對其進(jìn)行更改。

而且,在匿名課堂上,整個(gè)故事也就不足為奇了。 自從舊的Swing 1.0樣式好的ActionListener等以來,以下編碼樣式已通過匿名類泄漏了內(nèi)部狀態(tài)。

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樣式將鼓勵(lì)在各處使用Java中的高階函數(shù)。 這通常是好的。 但是只有當(dāng)高階函數(shù)是靜態(tài)方法時(shí),其結(jié)果類型才不會包含任何狀態(tài)。

但是,通過以上示例,我們可以看到,在不久的將來,當(dāng)我們開始接受Java 8的功能樣式編程時(shí),將通過一些內(nèi)存泄漏和問題進(jìn)行調(diào)試。

因此,請小心,并遵循以下規(guī)則:

(“純”)高階函數(shù)必須是Java中的靜態(tài)方法!

進(jìn)一步閱讀

封閉實(shí)例之前已引起問題。 了解過去二十年來可怕的雙花括號反模式如何在Java開發(fā)人員中造成痛苦。

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

總結(jié)

以上是生活随笔為你收集整理的提防Java中的函数式编程!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。