為什么Java仍很滋潤的活著?
我寫這篇很長的文章是對文章"為什么Java即將死去"的回應。我對此文本的評論名列前茅,我覺得我必須做出一個完全反對的聲明,這應該返回平衡。
對于作者的嘗試,最好的簡短答案是Coder:76的答案,它獲得了數百次鼓掌:
| "在過去的15年中,Java對那些希望引起關注的編程博客作者來說已經死了。" |
很難不同意。
" Java快死了"的說法有什么問題?
"為什么Java即將死去"的文章收到了70多個評論,其中大多數是關鍵評論,每個評論都有成千上萬的掌聲。為什么這么多人做出如此消極的反應?原因看起來很簡單:該文章以挑釁的方式撰寫,包含許多有爭議的陳述,對于使用Java的人來說,這些陳述遠非現實。讓我們來看看其中的一些。
| "例如,在這里,Spring可以在后臺設置自動裝配(bean注入),這是可以理解的,但是Lombok在應用程序上下文中的位置又是如何在兩者之間協調消息傳遞的呢?" |
對于使用上述技術的人們來說,這種說法是錯誤的。Lombok是一個編譯時庫,而Spring是一個運行時庫。它們在應用程序生命周期的不同時間以不同級別工作,并且不直接交互。對于作者的問題" Lombok在應用程序上下文中住哪兒?"的正確答案。是"沒有"。
| " Java的重點似乎仍然是愚蠢的規則,這些規則規定了應使用的類名,應使用的包以及變量是私有的還是受保護的。說真的,誰在乎?" |
從事大型,長期項目的人會照顧他們。這些規則對他們來說并不愚蠢。
| "相比之下,'我們都在這里成年'實際上是Python對該語言中缺少訪問說明的官方回應。" |
毫無疑問,團隊中的某人會認為其他人不是成年人,這是一個淺薄的主意。問題在于,由大型團隊創建的,持續時間很長的大型項目需要規則。否則,它們將失敗。大型項目就像一座大城市:它需要建筑基礎,規劃,關注點分離,私有和公共區域。如果熟練的程序員將語言結構分為公共結構和私有結構,則他們很可能會創建"街道",以正確的方式領導其他人,從而節省時間,并將輔助基礎設施隱藏在"地下",以至于沒有人迷路。
"為什么Java即將死去"一文中還有很多爭議性的陳述,但是我的目的不是詳細分析。我想做的是利用這次機會來談論Java本身的現代狀態。
多年來,Java是編程語言中的首選,同時也是批評家的首選。不是因為它不好,而是因為它是一件大事,如果想看起來比實際的大,必須說出反對某件大事的字眼,并祈求有人注意。從這個意義上講,Java是一個很好的目標。但是現在呢?Java是否仍然是一件大事,還是像某些人所說的那樣"瀕死"?讓我們討論最重要且值得商榷的主題,以便找出答案。
語法
> Image by Harry Fabel from Pixabay
Java的語法通常被批評最多:"不夠簡潔","不適合現代任務","太多樣板"等。對這些"參數"的唯一正確答案是顯示代碼。我將不在這里討論特殊的語法功能。有很多詳細的指南,涵蓋了Java語法的所有細微差別。相反,我僅選擇了五個代碼片段供您了解現代Java如何針對不同的實際任務進行操作。
- import static spark.Spark.*;
- public class HelloWorld {
- public static void main(String[] args) {
- port(80);
- get("/hello", (request, response) -> "Hello World");
- }
- }
上述代碼使用HTTP GET方法和/ hello上下文路徑在端口80上使用Spark Java啟動一個簡單的Web服務器,當請求時該上下文路徑將返回常量字符串。非常簡單明了,不是嗎?
- ...
- OrderRepository orders;
- QOrder qorder = QOrder.order;
- DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyy-MM-dd");
- public Iterable<Order> getShopOrdersByDate(ShopId id, ZonedDateTime date){
- return orders.findAll(
- qorder.shopId.eq(id).and(qorder.date.eq(yyyyMMdd.format(date)))
- );
- }
- ...
上述代碼結合使用Querydsl和Spring Data從SQL數據庫中獲取信息。一切看起來都非常簡單:方法getShopOrdersByDate返回具有特定日期和特定日期格式的特定商店的訂單。有趣的部分:這里沒有SQL,只有Java構造,以后會在庫中將其轉換為安全的SQL。這意味著查詢本身是類型安全的,并且在編譯時(而不是在運行時中)被可靠地檢查。而且,IDE可以像其他Java代碼一樣幫助您完成自動補全,使您的生活更輕松。開箱即用地支持大量數據庫,例如PostgreSQL,MySQL,Oracle甚至MongoDB。另外,如果要交換查詢代碼,則無需更改查詢代碼。
- import java.nio.file.Files;
- import java.util.stream.Stream;
- import static java.nio.file.Paths.get;
- import static java.util.stream.Collectors.*;
- public class Example {
- public static void main(String[] args) throws Exception {
- List<String> fileLines = Files.readAllLines(get("huge.txt"));
- String fileStats = fileLines.parallelStream()
- .flatMap(line -> Stream.of(line.split("\\s+")))
- .filter(word -> !"dumb".equalsIgnoreCase(word))
- .collect(groupingBy(word -> word.charAt(0), counting()))
- .entrySet().parallelStream()
- .map(letterStats -> letterStats.getKey() + ":" + letterStats.getValue())
- .collect(joining("\n"));
- System.out.println(fileStats);
- }
- }
這里沒有其他庫,只有純Java。從巨大的文件中讀取所有行,將其分成單獨的單詞,過濾出啞詞以保持所有內容的清潔,將單詞按第一個字母分組,計算每個組中的單詞數,創建結果組的字符串表示形式并進行計數,打印結果。可讀性強且易于維護。當然,所有事情都是在并行線程中完成的,以便于開箱即用地進行適當的加速,以便您的新16核怪物可以證明其成本合理。在里面裝有Java 15的4核筆記本電腦上,此代碼平均需要6秒鐘才能對填充有隨機單詞的1.2 Gb文本文件執行。對于這種文件大小和直接的未經優化的代碼來說還不錯。
- ...
- public MultiLayerNetwork createModel() {
- return new MultiLayerNetwork(new NeuralNetConfiguration.Builder()
- .regularization(true).l2(0.001)
- .learningRate(0.01)
- .weightInit(WeightInit.XAVIER)
- .activation(Activation.RELU)
- .optimizationAlgo(STOCHASTIC_GRADIENT_DESCENT)
- .updater(new Nesterovs(0.9))
- .list()
- .layer(convolution(5, 25).nIn(3).build())
- .layer(maxPooling(2).build())
- .layer(convolution(3, 50).build())
- .layer(maxPooling(2).build())
- .layer(convolution(3, 100).build())
- .layer(maxPooling(2).build())
- .layer(dense(200).dropOut(0.5).build())
- .layer(dense(200).dropOut(0.5).build())
- .layer(outputClassification(10))
- .setInputType(convolutionalFlat(28, 28, 3))
- .backprop(true).pretrain(false)
- .build());
- }
- ConvolutionLayer.Builder convolution(int filterSize, int filterCount) {
- return new ConvolutionLayer.Builder(filterSize, filterSize)
- .activation(IDENTITY).nOut(filterCount);
- }
- SubsamplingLayer.Builder maxPooling(int size) {
- return new SubsamplingLayer.Builder(PoolingType.MAX)
- .kernelSize(size, size).stride(size, size);
- }
- DenseLayer.Builder dense(int size) {
- return new DenseLayer.Builder().nOut(size);
- }
- OutputLayer outputClassification(int numOfClasses) {
- return new OutputLayer.Builder(LossFunction.MCXENT)
- .nOut(numOfClasses).activation(SOFTMAX).build();
- }
- ...
這個簡單的示例顯示了在學習階段之前使用Dl4j準備神經網絡結構的階段。那些處于深度學習領域的人將輕松識別許多熟悉的單詞。沒什么特別的。是的,您通常可以使用Java進行深度學習和機器學習。
- import lombok.AllArgsConstructor;
- import lombok.Data;
- @Data
- @AllArgsConstructor
- public class User {
- String name;
- String surName;
- List<ContactInfo> contacts;
- }
你討厭樣板嗎?然后使用lombok。此代碼片段顯示了功能齊全的數據類,其中正確完成的所有字段上均具有getter,setter,equals,hashcode,toString,最后是AllArgsConstructor。如果愿意,您當然可以覆蓋其中的任何一個。
來自Java生態系統外部的人們通常會爭辯說" Lombok使Java不是Java。"我不同意:Lombok是Java。它是現代Java生態系統的一部分,使用合法的Java機制來添加其功能,可以幫助您處理幾乎零缺點的Java代碼,并且受到許多Java開發人員的喜愛。多少?最流行的Java IDE之一將Lombok插件下載數量估計為11+百萬。許多。這是一種使Java更好的工具,因此從實際意義上講,它是數百萬使用Java的人的Java。不過,Java社區中有一部分人反對Lombok,他們擁有這樣做的全部權利-如果您不喜歡Lombok,則沒有人會強迫您這樣做。
現在想象一下這些示例在其他語言中的外觀。您可能會發現用于達成相同目標的語言所包含的字符要少一些。但是,該代碼是否會像Java語言一樣可靠,可讀性,可維護性和快速性?我幾乎不這么認為。
與語法相關的另一重要事項是IDE支持。這不是抽象的理論問題,例如語言結構的強大程度或開發人員必須編寫多少符號才能執行某項操作。 IDE添加了一個實用層,將所有抽象問題轉換為一個問題:特定任務將花費多少開發人員時間。將精心設計的語言與現代IDE結合使用,與使用功能更強大或更簡潔但對IDE友好程度更低的語言相比,開發人員可以更快地達到目標。 Java具有以下語法,這是Java最好的IDE支持之一:它不太復雜,同時也不太自由選擇,因此IDE可以了解您當前正在使用的上下文并預測您想做什么。接下來非常精確。最后要說的是,Java的語法允許使用不同的編程樣式。您的代碼可以用面向對象的范例編寫,其中對象彼此交互。在程序范式中,命令式程序調用的順序改變了全局狀態;或在功能范式中,您可以組合和應用功能以實現目標。有時人們會區分更多的范例-例如,Java非常適合面向方面或基于參與者的范例。 Java為您提供了極大的靈活性,使您可以思考自己的任務,因此它為應對周期性發生的編程范式時尚轉變做好了充分的準備。
綜上所述,Java的語法沒有問題。它相對簡單,靈活且富有表現力。此外,它還允許IDE通過多種方式有效地幫助開發人員,從而大大提高了他們的生產率。如果您精通Java,編寫清晰的代碼,并使用正確的工具集來完成任務,那么您的程序將是美觀,可維護和簡潔的。不要讓人們在這個話題上欺騙您。
保證
> Photo by Joshua Hoehne on Unsplash
與許多其他技術不同,Java作為一種語言和平臺為您提供了許多可以依賴的保證。
Java語言具有Java語言規范,這是對Java代碼的構造應該如何工作和應該如何使用的主要判斷。它為什么如此重要?因為您可以驗證自己的工作并以嚴格,可預測的方式解決問題或糾紛。對于沒有規范的語言,您不太確定會發生什么情況:您可能會在手冊,博客或語言創建者的推文中找到一些信息,但是直到語言獲得規范,所有這些信息才具備保證一切的堅實基礎。
當然,規范可能具有不同的質量或不同的詳細程度,因此可能會遺漏某些內容。盡管如此,具有規范的語言比沒有語言的語言給您提供了更高的信心,使您確信自己在做正確的事情。Java的規范非常深入和詳細,幾乎沒有歧義。
Java版本對規范和公共Java API中的內容具有強烈的向后兼容性。這意味著,如果您使用使用20年前編寫的版本1.3的公共Java API的代碼,并且今天在Java 15上運行它,它將可以正常工作。同時,如果您使用私有Java API,該API由不應由開發人員直接使用的類和方法/字段組成,則可能會遇到麻煩。我認為這很合理:如果您使用可以保證向后兼容的產品,則可以依靠它,但是如果您使用了不打算使用的產品,請不要期望它們永遠有效。
Java是安全可靠的-并非絕對如此;實際上。Java代碼是安全的,因為與許多其他語言相比,開發人員使用Java代碼出錯的可能性較小。從Java代碼不能直接訪問操作系統或硬件的角度來看,這是安全的,因此Java運行時可以安全地限制Java程序可以做什么和不能做什么。
Java代碼是可移植的。這意味著您可以在一個平臺上編譯Java代碼,并且可以在實現Java虛擬機的任何平臺上運行它,而無需重新編譯。"編寫一次,隨處運行" –古老的Java標語,直到25年后的今天仍然可行。廣泛的可移植性以及向后兼容性是保證的非常強的組合,這使開發人員確信他們的努力和知識不會很快過時。當然,在某些特殊情況下,由于諸如硬件限制之類的各種原因,某些虛擬機僅允許Java語言規范的子集。例如,您可以在8kB RAM微控制器上運行Java代碼,但是必須考慮一些限制。
Java代碼是可維護的。與C ++之類的語言相比,Java的語法非常簡化。它缺乏C ++具有的許多功能,自定義項和強大的構造。同時,與腳本語言相比,Java具有許多乍一看都是多余的"儀式"。從這個意義上講,Java試圖在復雜性,功能和可讀性之間保持平衡,以最大化長期代碼可維護性。什么是可維護性?我將其描述為普通技術開發人員將更改應用于現有代碼庫(可能是舊代碼庫)所需的時間,這可以達到開發人員的目標,并且不會破壞其他任何東西。所需時間越短,可維護性就越高。
從這個意義上講,Java是好的。一方面,它功能強大,足以表達開發人員所需的許多內容,但同時又不像語言那樣復雜,人們可以使用極其強大的語言構造(只能由其創建者理解)來創建精美,無法解決的迷宮。另一方面,Java要求開發人員編寫比開發人員通常用腳本語言編寫的更詳盡的代碼,并且編寫更明確的內容,以提高可讀性并易于理解時間流逝后發生的事情。
Java很快。如果您嘗試研究此主題,可能會發現許多文章,例如" Java比X快"和" X比Java快",其中包含矛盾的陳述和結論。如果您嘗試進行實驗,則可以輕松地構造Java速度慢而Java快速發展的示例-順便說一句,您可以使用其他語言來完成相同的技巧。關于為什么過去認為Java速度很慢有很好的評論。現在有點過時了。例如,最新的Java運行時中的字符串處理要比七年前好得多,而且我也不同意其他一些聲明。但是總的結論是,對于每個發行版,Java都會進行優化以提高其性能。還記得本文"語法"部分的第三個示例,其中處理了巨大的1.2 Gb文件?使用Java 8,在我的筆記本上平均要花十秒鐘,而使用Java 15,只有相同配置的六秒鐘。這是該語言的開發人員為我們提供的重要保證之一:Java足夠快,足以應付當今的許多任務,并且將來會更快。
關于擔保的最后一件事要說的是:它們已經實現了25年以上,并且沒有理由在未來的幾年中不會實現。
Java緩慢實現現代語言功能
> Photo by Makarios Tang on Unsplash
是。通常,慢是一件壞事嗎?不。問自己以下。如果您騎著自行車,偶爾看到前方的墻壁,您會喜歡什么:加速還是減速?我打賭你選擇和我一樣。
那么,為什么Java采用的功能比其他某些語言的速度慢?由于擔保,我們在上一節中討論過。這些保證就是一堵墻,它迫使對功能進行仔細地討論,過濾或以某種方式進行變換,在這里,慢是比著急更好的朋友。關于如何將更改應用于Java語言的正式過程稱為Java社區過程。此過程的主要目的是驗證所提出的功能不會破壞保證。有時候,這并不是一項顯而易見且快速的任務。
Java語言的開發人員試圖在創新和保證之間保持平衡,這比"讓我們現在將這種很酷的功能添加到我們的語言中"要難得多。但是,從長遠來看,它可以帶來更多利潤,因為保證意味著信任,這對未來來說比有價值的功能集更有價值。Brian Goetz討論了Java的這種策略和總體哲學。請看一看。
另外,值得一提的是當前的Java發布時間表。9月和3月每六個月發布一次Java的新版本,該版本完全可以使用,并在接下來的六個月中逐步更新。每三年,其中一個這樣的版本將成為長期支持(LTS)版本,并在接下來的三年中逐步更新。現在,Java 15是最新版本,而Java 11是當前的LTS。LTS的下一個發行版將是Java 17,計劃于2021年9月發布。每個版本都可以包含許多"預覽功能",對于這些功能,不能保證將來的發行版具有兼容性。他們的目標是為開發人員提供嘗試有爭議的創新并留下反饋的可能性。如果某個功能未標記為預覽,則表示該功能已完全包含在平臺中,并將具有Java提供的所有保證。
生態系統
> Photo by Greg Rakozy on Unsplash
有些人狹義地理解語言生態系統,僅將其概念限制為程序員可以使用的一組庫。我更傾向于將生態系統視為解決問題的工具。開發人員可以用該語言解決的問題越多,其生態系統就越廣泛。優先選擇哪個含義都沒有關系:Java具有龐大的生態系統。
這是我之前問自己解決我遇到的問題的個人隨機問題列表:
- 我可以使用對HTML,JS和CSS零知識的純Java編寫Web應用程序嗎?是。
- 我可以在毫秒級的世界范圍內使用TB級的堆嗎?是的,很容易。
- 我可以用純Java處理圖像和視頻以實現可移植性嗎?是。
- 我可以使用Java進行深度學習嗎?是的,請。
- 我可以使用Java對在黑色星期五購買的機器人進行編程嗎?是。
- 我可以找到有關Java的隨機愚蠢問題的答案嗎?是。
該列表絕對是個人的,但是我可以肯定,在大多數情況下,當問題在編程環境中并且涉及Java時,"是"的實例將壓倒"否"的實例。
在Java生態系統的幫助下,您可以解決許多領域中的許多問題,此外,通常您也有多種選擇方式。如果您想了解Java生態系統的廣闊程度,請查看此資源。
啟動時間和內存占用量
> Photo by Bill Oxford on Unsplash
Java代碼被編譯為稱為Java字節碼的中間形式,然后在稱為JVM的運行時平臺上執行。除了抱怨Java語法外,評論家通常還會抱怨JVM內存占用量和啟動時間。讓我們更詳細地討論。
JVM代表Java虛擬機,這意味著您的應用程序由虛擬計算機在沙箱中運行。這種方法有很多好處。開發人員無需考慮運行應用程序的操作系統和硬件的細微差別。虛擬沙箱提供了更高的安全性,因為它不允許應用直接與低級事物進行交互。虛擬環境位于您的應用程序外部,可以動態優化它,以提高在不同情況下的性能等。
缺點是JVM需要額外的資源(包括內存和處理器時間)才能運行,并且具有啟動和預熱時間。
在通常的使用情況下,根據應用程序的不同,標準的Oracle HotSpot JVM會引入數十或數百兆字節的額外空間,平均需要幾秒鐘的啟動時間。(JVM本身通常在不到一秒鐘的時間內啟動,但是其他一些庫由于其內部例程而增加了該時間。)而且,在啟動后的最初幾秒鐘內,JVM可以消耗比平均更多的CPU,因為它可以識別并編譯"字節碼中的"熱門"部分以優化其將來的用法。
在大多數情況下,這些缺點對于許多類型的應用都是合理的。但是在某些情況下,它們并非如此,您希望以某種方式權衡利弊。那你該怎么辦?您是否應該放棄Java而改用其他東西?通常不會-僅選擇另一個適合您特定任務的運行時。
考慮例如微服務域。現代微服務應用程序通常需要最少的內存占用空間和啟動時間,以有效地填充Kubernetes等容器編排器。為了滿足這一需求,Java開發人員創建了GraalVM。它允許開發人員從Java代碼創建本機映像,這些映像將在數十毫秒的啟動時間和僅幾兆字節的額外內存占用下運行。許多Java Web框架使GraalVM適應微服務領域:Quarkus,Micronaut,Spring和Helidon。
交易弊端?您將失去可移植性,并且生成的映像只能在GraalVM為其編譯的平臺上運行。但是對于微服務而言,這并不是很重要,因為您的應用很可能會在具有預定義環境的容器中運行。您可能還會面臨其他一些限制。無論如何,當您聽到Java不適合現代微服務需求時,請記住:該陳述是錯誤的。
正如許多批評家所說,Java并不意味著過度使用內存和縮短啟動時間。內存使用情況和啟動時間主要取決于最終運行應用程序所用的運行時以及所使用的其他庫。從這個意義上講,Java生態系統根據您的需求為您提供選擇。
Java真正的目的是什么?
> Photo by Xavi Cabrera on Unsplash
Java可以用于您想像的一切:API和Web服務器,游戲和多媒體軟件,UI和Web應用程序,IoT和機器人技術,AR和VR,機器學習和數據流,數據庫和云原生微服務,大型企業系統和小原型。有沒有排除事項?技術上不,實際上是。Java并不是低級系統語言,因此用Java創建操作系統或硬件驅動程序的核心不是一個好主意。從技術上講是可能的,但是針對這些情況,有比Java更好的工具。
但是我們必須為Java付費,對吧?
> Photo by Jp Valery on Unsplash
不,如果您使用免費的Java發行版,則不必為Java付費。Java是開源的,因此任何人都可以構建現成的Java發行版,并且有許多免費的預構建發行版,例如OpenJDK,AdoptOpenJDK,AWS Coretto,Azul Zulu等。這些發行版的使用是絕對免費的,并且它們中的任何一個極有可能滿足您的要求。如果您想了解更多有關此信息,請參閱本文。
Java的未來
> Photo by Karsten Würth on Unsplash
總結一切:Java仍然是一個很重要的語言。
它的作用是成為許多領域的核心技術,在創新,功能和可維護性之間取得平衡,以可持續地支持所使用的項目。如果您想嘗試新穎的語言構想,請選擇另一種技術。但是,如果您看到某個特定功能最終找到了它成為Java規范的方式,則可以確定不是由于偶然的情況或很小的時尚波動而添加了該功能,而是經過深入研究和為達到相同水平而付出的巨大努力設計的結果保證其他Java功能具有。從這個意義上講,您可以信任Java,這與市場上的許多其他技術不同。
如果您在問初學或初學時應該學習哪種計算機語言,只需嘗試一下Java。我敢肯定Java將在我們身邊住很長時間。
我敢打賭,關于Java為什么會長壽,本文還遺漏了許多其他好的論點,歡迎您在評論中分享它們。
原文鏈接:https://medium.com/better-programming/why-java-is-perfectly-alive-e3f25a576f95
【責任編輯:趙寧寧 TEL:(010)68476606】
























