函數式編程java
A. java lambda表達式是什麼
lambda表達式是JAVA8中提供的一種新的特性,它支持JAVA也能進行簡單的「函數式編程」。它是一個匿名函數,Lambda表達式基於數學中的λ演算得名,直接對應於其中的lambda抽象(lambda abstraction),是一個匿名函數,即沒有函數名的函數。
函數式介面:
這個是理解Lambda表達式的重點,也是產生lambda表達式的「母體」,這里我們引用一個比較容易理解的說法:函數式介面是 一個只有一個抽象方法(不包含object中的方法)的介面。
這個需要說明一點,就是在Java中任何一個對象都來自Object 所有介面中自然會繼承自Object中的方法,但在判斷是否是函數式介面的時候要排除Object中的方法。
B. java函數式編程是炫技編程嗎
函數式編程(Functional Programming)是一種編程風格,它是相對於指令式編程風格而言的,常見的面向對象編程就是指令式編程風格。
指令式編程是面向計算機硬體的抽象,有變數(對應著存儲單元),賦值語句(獲取、存儲指令),表達式(內存引用和算術運算)和控制語句(跳轉語句)。
而函數式編程是面向數學的抽象,將計算描述為一種表達式求值。這里的函數實際就是數學中的函數,即自變數到因變數的映射。也就是說,一個函數的值僅決定於函數參數的值,不依賴其他狀態。
函數式編程是一種抽象程度很高的編程範式,純粹的函數式編程語言編寫的函數沒有變數,因此,任意一個函數,只要輸入是確定的,輸出就是確定的,這種純函數我們稱之為沒有副作用。而允許使用變數的程序設計語言,由於函數內部的變數狀態不確定,同樣的輸入,可能得到不同的輸出,因此,這種函數是有副作用的。
在函數式語言當中,函數作為一等公民,可以在任何地方定義,在函數內或函數外,可以作為函數的參數或返回值,可以對函數進行組合,也可以將函數賦值給變數。嚴格意義上的函數式編程意味著不適用可變的變數,賦值,循環和其他命令式控制結構進行編程。
函數式編程風格帶來的好處是:
函數式編程使用不可變對象作為變數,不會修改變數的值,而是返回一個新的值,如此這樣,更容易理清頭緒,使得單元測試和調試更加容易;
可以很自由地傳遞不可變對象,但對於可變對象來說,傳遞給其他代碼之前,需要先建造一個以防萬一的副本;
一旦不可變對象完成構造以後,就不會有線程因為並發訪問而破壞對象內部狀態,因為根本沒有線程可以改變不可變對象的狀態;
不可變對象讓哈希表鍵值更安全,所以哈希表鍵要求必須是不可變對象,否則使用可變對象,如果對象狀態發生變化,那麼在哈希表中就找不到這個對象了;
具體到編程語言,Scala(靜態語言)和Python(動態語言)都能比較的支持函數式編程風格,但是它們都不是純函數式的,也就是說它們同時支持指令式風格和函數式風格。而Java基本是指令式風格,但自從Java8引入lambda表達式以後也開始部分支持函數式風格。函數式編程最典型的是諸如map, flatMap, rece, filter等函數,它們的特點是支持某個函數作為上面這些函數的參數
C. Java8的函數式編程怎麼樣
使用函數式代碼的好處:
減少了可變數(Immutable Variable)的聲明
能夠更好的利用並行(Parallelism)
代碼更加簡潔和可讀
函數式介面
函數式介面就是僅聲明了一個方法的介面,比如我們熟悉的Runnable,Callable,Comparable等都可以作為函數式介面。當然,在Java 8中,新添加了一類函數式介面,如Function,Predicate,Consumer,Supplier等。
D. java開發的缺點有哪些
我認為Java語言的10大問題是:x0dx0a1、缺少閉包(closure):我想這個不需要解釋了。函數式編程已經存在幾十年了,但最近幾年,它們獲得了越來越多的關注,最主要的原因,是它可以自然地編寫並行程序。我部分的同意Joshua Bloch強調在Java中引入閉包的問題需要再想一想(BGGA提議的方式真的很糟),至少閉包的缺失,使得在Java中做任何真正的函數式編程都是不可能的。x0dx0a2、缺少一等函數:這個問題與前一個有些關聯,但我認為它更糟糕。在Java里,要達到類似效果的唯一方式,是使用著名的、醜陋悲慘的單方法匿名內部類,但這看上去的確是一個拙劣的方法。甚至在C#中,也通過代理機制,提供了一個更好的實現。x0dx0a3、原生類型(Primitive types):如果在Java中一切皆對象,那是多麼完美啊,但他們偏偏不這樣設計。因而,這一點導致了一些問題,比如,不能把一個int放到集合(Collection)里,這個在Java5中通過自動裝箱特性得到了解決(下面會提到)。它也造成了傳值與傳引用上的困擾,原生類型數據是通過值傳給方法的(復制一份拷貝,然後傳給函數),而真正的對象是通過傳遞(譯註:其實是復制對象地址再傳遞,因此應該也是傳值方式,只是由於函數內部可通過這個對象地址訪問對象,因此效果上類似傳引用)。x0dx0a4、自動裝箱(Autoboxing)和自動拆箱(autounboxing):這個特性是為了解決因原生類型的存在所導致的問題,在Java5引入的。它允許靜默地轉換原生類型到相應的對象,但這常常導致其它的問題。比如Integer可以為null,但int不能,因此這時JVM只能拋出一個難以調試的空指針異常(NullPointerException)。此外,它還可能導致其它奇怪的行為,就像下面的例子,我們就很難理解,變數test為什麼是false:x0dx0aIntger a = new Integer(1024);x0dx0aIntger b = new Integer(1024);x0dx0aboolean test = a < b || a == b || a > b;x0dx0a5、缺少范型具類化:范型是Java5引入的一個很酷的特徵,但是為了保持與舊版本Java的兼容性,導致缺失某些重要的特性,尤其是不能在運行時反省范型的類型。例如,你有一個方法,接受List參數,如果傳進來一個List,你卻不能知道運行里該范型的確切類型。同理,你也不能創建范型數組。這意味著,盡管下面的代碼看起來很自然,但卻不編譯不了:x0dx0aList[] listsOfStrings = new List[3];x0dx0a6、不可避免的范型警告:你有發現過自己陷入不可能去掉的關於范型的警告么?如果你像我一樣大量使用范型,我打賭你碰到過。事實上,是這個問題的規模化症狀,讓他們認為需要引入一個特定的註解(@SuppressWarnings("unchecked"))來處理這種情況,我覺得,范型應該可能被設計的更好。x0dx0a7、不能傳void給方法調用:我得承認,這種給方法傳遞void的需求,乍一看有些怪異。我喜歡DSL,當我實現自己的DSL庫(lambdaj)的一個特定特性時,我不得不需要一個方法聲明成這樣的簽名:void doSomething(Object parameter),這里為這個方法傳進來的參數parameter,是另一個方法調用的結果,它唯一的目的,是注冊調用(的對象)自身,以可以在以後執行它。讓我吃驚的是,即使println方法返回void,看上去也並沒有一個好理由,不允許我把代碼寫成這樣,:x0dx0adoSomething(System.out.println("test"));x0dx0a8、沒有原生的代理機制:代理是一種非常有效和應用廣泛的模式,但Java提供的代理機制,只針對介面,而不是具體類。這是為什麼象cblib這樣提供這種機制的庫,被如此多的主流框架,如Spring和Hibernate,採用的原因。此外,由於cglib通過運行時創建被代理類的子類來實現的,因此這些種方式有一個眾所周知的限制——不能代理final類,比如String。x0dx0a9、差勁的Switch...case語句:Java規定,switch...case只能選擇int和enum(Java5開始)。這一點如果跟更現代的語言如Scala相比,看起來簡直太弱了。x0dx0a10、受檢查異常(Checked exception):類似原生類型,受檢查異常也已經成為Java的一個罪孽之源。它迫使程序員必須做下面兩件極其糟糕討厭的事情中的一個:讓你的代碼里充斥大量的、糟糕難讀的、容易出錯的try...catch語句,而這樣做的最大意義,只是將捕獲的異常,包裝成運行時異常,然後再重新拋出;或者是讓大量的拋出聲明子句污染你的API,讓介面缺少靈活性和可擴展性。x0dx0a真正的問題是,這里我提到的這幾大主要問題,唯一的解決辦法,是要做一個痛苦的決擇,定義一套新的語言規范,放下當前版本的向後兼容性。我猜他們永遠也不會這么做,雖然我相信,如果編寫一個能夠自動轉換舊Java源碼的程序,讓它們與假設的新版本兼容,並不是很困難。最後,這就是我決定開始尋找一個更好的JVM兼容語言的原因。
E. java支持的編程範式
Java編程範式
1.命令式編程
核心內容就是:「用語句更改程序的狀態」
大多數流行的編程語言都或多或少基於命令式編程發展而來,命令式語言最典型的實例就是C語言
2.面向對象編程
面向對象編程經常與命令式編程聯系在一起,在實踐當中,兩者是可以共存的。Java就是這種協作的生動證明
面向對象基於四個基本原則:封裝、繼承、多態、抽象
3.聲明式編程
與命令式編程相反,聲明式編程它指定程序應該做什麼,而不具體說明怎麼做。
純粹的聲明式語言包括資料庫查詢語言(如SQL和Xpath)以及正則表達式。
與命令式編程語言相比,聲明式編程語言更加抽象,它們並不模擬硬體結構,因此不會改變程序狀態,而是將它們轉換為新狀態,並且更接近數學邏輯
通常,非命令是的編程範式都被認為屬於聲明式類別。
4.函數式編程
函數式編程是聲明式編程的子範式,與命令式編程相反,函數式變成不會改變程序的內部狀態。
在函數式編程術語中,函數類似於數學函數,函數的輸出僅依賴於其參數,而不管程序的狀態如何,完全不受函數式是何時執行的影響
函數式語言受歡迎的原因之一是它們可以輕松的在並行環境中運行,這與多線程不太一樣,函數式語言支持並行的關鍵在於它們的基本原理:函數僅依賴與輸入參數而不依賴於程序的狀態。它們可以在任何地方運行,然後將多個並行執行的結果連接起來並進一步使用
F. Java函數式編程語言是什麼
函數式編程語言的核心是它以處理數據的方式處理代碼。這意味著函數應該是第一等級(First-class)的值,並且能夠被賦值給變數,傳遞給函數等等。
事實上,很多函數式語言比這走得更遠,將計算和演算法看得比它們操作的數據更重要。其中有些語言想分離程序狀態和函數(以一種看起來有點對立的方式,使用面向對象的語言,這通常會將它們聯系得更緊密)。
Clojure編程語言就是一個這樣的例子,盡管它運行於基於類的Java虛擬機,Clojure的本質是函數式語言,並且在高級語言源程序中不直接公布類和對象(盡管提供了與Java良好的互操作性)。