c++返回指针时候注意提防_提防Java中的函数式编程!
c++返回指針時候注意提防
這對函數式編程并不會造成太大的影響,這真棒。 這是關于某些實踐的警告,您很可能會將其應用于您的代碼,而這是完全錯誤的! 。
高階函數對于函數式編程是必不可少的,因此,談論它們將幫助您成為聚會中的關注焦點。
如果您正在編寫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實例:
精細。 當然。 讓我們添加一些其他日志記錄,僅用于調試
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類中:
隨之而來的是沉重的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
c++返回指針時候注意提防
總結
以上是生活随笔為你收集整理的c++返回指针时候注意提防_提防Java中的函数式编程!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全球十大催泪感人电影排行榜(10部从头哭
- 下一篇: 800米跑步标准成绩(800米跑步的各项