如何評價Java

来源:https://www.cnblogs.com/xiaoyangjia/archive/2023/03/26/17256055.html
-Advertisement-
Play Games

Java已經誕生20多年了,依然是企業級開發中使用最廣泛的語言,也是挨罵最多的語言。Java廣受批評的四個缺點是:性能差、記憶體消耗大、GUI弱、代碼啰嗦,我們應該如何看待這幾個問題呢?在微服務的背景下,提倡圍繞業務能力而非技術來構建應用,允許由不同的語言構建應用程式。一個超大的集群,往往有上萬個微服... ...


1 語言優劣論

世上只有兩種編程語言:一種被人罵,一種沒人用。

Java已經誕生20多年了,依然是企業級開發中使用最廣泛的語言,也是挨罵最多的語言。技術圈經常有“A語言比B語言更好”的爭論,爭論的核心有兩點:語法和性能,比如“Java性能不如C#、Python語法比Java優雅”。

先談談語法的優劣。每個開發者都有自己偏愛的語法。你覺得很舒服的寫法,就有人覺得彆扭,這是個主觀問題。比如Java 8 中的Lambda表達式,可以極大的優化集合操作的代碼結構,但是不少人反感 () -> {} 這種符號,不願意在項目中使用。再舉個例子,Java語言定義變數的方式是數據類型前置、變數名後置,如: int maxSize = 100;而Go語言中變數名是前置的,如:var maxSize int = 100,寫慣了Java的人肯定不適應變數名前置。習慣的力量太大了,許多人將自己的偏愛當成評判的標準。

再談性能的優劣。編程語言的開發團隊固然希望性能更好,但是性能優化要一步一步來。我們要用發展的眼光看待性能問題,早期的Java編譯器和虛擬機性能確實堪憂,發展到如今已經改善了不少,以後也會繼續提升。如果一款語言性能真的差到無法接受,絕不會用於企業開發中。每種語言的使用場景不同,C語言的性能固然高於Java或者C#,為什麼沒有人C開發Web項目?在需求快速迭代的項目里,開發效率更重要,性能夠用就行,通俗的說就是人比機器貴。通常項目中遇到的大部分的性能瓶頸,降級需求或者優化設計方案就能解決,許多程式員的水平還沒有達到可以指責語言性能的程度。

企業選擇某款編程語言作為生產力工具,首先考慮的是人力招聘和培養的成本,其次才是語言特性和開發效率。這些年出現了許多新語言如Golang、Rust,也許概念更先進、性能更好,但是企業不會輕易在核心系統上採用新語言,以免出現不可預估的風險,保持系統的穩定才是最重要的。

2 Java的爭議

1995 年 5 月 23 日,Java 正式發佈。經過20多年的發展,Java孕育出了大量的開源組件和開發者。在它誕生的年代,相比其他語言有五個優勢:
(1)簡單易學:沒有指針操作和手動記憶體分配,易學易用,程式員心智負擔較小。
(2)面向對象:僅支持面向對象編程,單一的編程範式可以避免工程過度複雜。
(3)網路編程:提供了更簡單的網路編程庫,適合構建大型的網路分散式系統。
(4)反射機制:通過反射機制增強了語言的動態性,大部分開發框架都用到了這個特性。
(5)跨平臺:通過JVM屏蔽了底層硬體的差異性,為上層應用提供統一的介面。應用程式被編譯成與電腦結構無關的位元組碼,可以運行在不同的操作系統中。

事物總是有兩面性,為瞭解決一個問題引入一個特性,也必然帶來新的問題。我們應該如何辯證的看待Java廣受詬病的幾個問題呢?

  • 性能差

通常有GC語言不提供非常底層的記憶體操作方法,因此不可能達到無GC語言的性能,而且當虛擬機徹底回收垃圾時,應用程式會被強制停止,某些需要低延遲的場景絕不能接受這種狀態。事實上,如果進行數值計算的基準測試,Java比 C++沒有慢多少,企業開發中的Java項目速度慢的根本原因是框架濫用反射,載入反射代碼要比普通程式慢幾十倍,編譯器沒法優化反射代碼。在資源緊張或者高性能場景下,C / C++仍然是首選,Java無法勝任。

  • 記憶體占用大

Java應用程式啟動後包含JVM實例,一個“Hello World”都要消耗幾十兆記憶體。每個Java的對象都要包含一個96 bits的對象頭,一個32bits的integer就要占用記憶體96bits+32bits=128bits。向Go這種面向值的語言,每個值的存儲消耗最低僅為2bits。企業級框架Spring大量採用HashMap緩存數據,也是極度消耗記憶體的。

  • GUI弱

Java桌面軟體的性能低、開發體驗也差。最新的GUI庫JavaFX比Swing、AWT進步很多,但是遠遠不如Qt(C++)、WinForm / WPF (C#) 等框架。從商業角度考慮,多數企業軟體並不需要跨平臺,運行在Winows就足夠了,少量的要相容MacOS,Java跨平臺特性在這種情況下反而是雞肋。谷歌選擇Java語言開發Android應用,看重的是龐大的Java生態,而不是語言特性。

  • 代碼啰嗦

Java僅支持面向對象編程範式,書寫起來極為啰嗦,比如main方法不能是一個獨立的函數,必須放在沒有實際意義的class中。好處是風格統一,壞處就是死板和啰嗦。採用Spring框架開發的Java項目,只要遵循基本的代碼規範,每個人寫出來的都差不多,可讀行不會太差。與之相反,C++這種多範式語言,非結構化、結構化、面向對象、巨集、模板等等應有盡有,靈活性極大,要精通也很難。維護一個大型的C++項目,就像在讀一本百科全書。

3 雲原生的考驗

雲計算是一種實施模式,是指通過互聯網方式交付存儲、伺服器、應用等等。“雲”是一種管理 IT 資源的方法,能夠取代本地設備和私有數據中心。在雲計算模式下,用戶無需購買和維護大量的計算、存儲和其他 IT 基礎設施,直接訪問雲計算提供商的計算、網路和存儲資源即可。雲服務提供商能夠保障物理設備的正常運轉、資源的按需調配等等。

雲原生是一種構建和運行應用程式的方法,是一套技術體系和方法論。雲原生是Cloud+Native的組合詞,Cloud表示應用程式位於雲中,而不是傳統的數據中心;Native表示應用程式從設計之初即考慮到雲的環境,原生為雲計算而設計,可以充分發揮雲計算平臺的彈性和分散式優勢。雲原生架構有4個重要的實施原則:
(1)DevOps:採用自動化工具將應用快速部署到生成環境,並且讓開發、運維互相協作。
(2)持續交付:支持頻繁持續的發佈應用,快速反饋部署故障,有效降低發佈風險。
(3)微服務:將龐大複雜的單體服務拆分為更小的微服務,每個微服服可以快速、獨立的部署。
(4)容器化:將應用程式及依賴項打包成鏡像,以容器化的方式快速分發。

在虛擬化技術沒有廣泛應用的階段,部署應用程式是個繁瑣的事情。為了讓程式在Linux、Windows等平臺以及x86、AMD64、SPARC、MIPS、ARM等指令集架構上都能正常運行,必須先將源碼編譯為對應的可執行文件,或者直接分發源代碼,由使用者自行構建可執行文件。Java發佈時,提出了一句動人的口號:一次編寫,到處運行”(Write Once, Run Anywhere),解決了應用部署的痛點。在雲原生架構下,Java以及JVM的特性面臨了新的挑戰。

在微服務的背景下,圍繞業務能力而非技術來構建應用,允許由不同的語言構建應用程式。一個大型的微服務集群,往往有成千上萬個容器在運行。為了更有效率的管理容器,對微服務有幾個訴求:鏡像體積小、記憶體消耗少、啟動速度快,這些卻都是Java的弱項。再小的Java程式也帶著完整的虛擬機和標準類庫,這樣會降低拉取鏡像和創建容器的效率;Java的程式都會有固定的基本記憶體開銷和啟動時間,開源框架Spring等廣泛採用的依賴註入也使得容器的啟動時間過長。最好解決方案是,將Java源碼直接編譯為二進位可執行文件,再將可執行文件打包為鏡像。

GraalVM是Oracle實驗室推出的基於Java開發的開源高性能多語言運行時平臺,它既可以在傳統的 OpenJDK 上運行,也可以通過 AOT(Ahead-Of-Time)編譯成可執行文件單獨運行。GraalVM將源代碼打包成可執行代碼,運行時不包含JRE,實現秒級別的啟動,占用記憶體更小。

知名開源框架 Spring 的研發團隊也發佈了 Spring Native 項目,利用 GraalVM 將 Spring 應用生成可執行的原生鏡像(Native Image)。這些原生鏡像的啟動速度極快、記憶體消耗也更少,但是比JVM的構建時間更長、運行時優化也不足。目前 Spring Navtive 仍然處於孵化階段,國內公司用於生產環境的很少。

參考
https://www.cnblogs.com/JaxYoun/p/16483067.html
https://zhuanlan.zhihu.com/p/333926379
https://zhuanlan.zhihu.com/p/150190166
https://www.codingbrick.com/archives/1130.html

博客作者:編碼磚家
公 眾 號:編碼磚家
獨立博客:codingbrick.com
文章出處:https://www.cnblogs.com/xiaoyangjia/p/17256055.html
本文版權歸作者所有,任何人或團體、機構全部轉載或者部分轉載、摘錄,請在文章明顯位置註明作者和原文鏈接。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 前面我們簡單的瞭解了 vue 初始化時的一些大概的流程,這裡我們詳細的瞭解下具體的內容; 內容 這一塊主要圍繞init.ts中的initState進行剖析,初始化生命周期之後緊接著。 initState initState的方法位於scr/core/instance/state.ts中; co ...
  • 定義 代理是一個中間者的角色,如生活中的中介,出於種種考慮/限制,一個對象不能直接訪問另一個對象,需要一個第三者(中間代理)牽線搭橋從而間接達到訪問目的,這樣的就是代理模式。 es6 中的代理 es6 的 proxy 就是上面說的代理模式的實現,es6 幫我們在語法層面提供了這個新的api,讓我們可 ...
  • 使用工具: IDEA2022 Tomcat9.0.4 1.下載Tomcat: 官網:https://tomcat.apache.org/ 找到需要的版本下載即可,下載完成解壓即可用: Tomcat目錄介紹: 1.1.Tomcat啟動、關閉。卸載: 啟動:雙擊bin\startup.bat 關閉:直接 ...
  • 委托模式(Delegation pattern):將一個對象的某個方法委托給另一個對象來執行,它可以幫助我們將對象之間的關係更加靈活地組織起來,從而提高代碼的可維護性和復用性。 在委托模式中,一個對象(稱為委托對象)將一些特定的任務委托給另一個對象(稱為代理對象)來執行。代理對象通常具有和委托對象相 ...
  • 1.聲明與變數 let聲明的變數可以多次賦值 let 變數名 = 值; const修飾叫常量,只能賦值一次,但是引用的值可以改變 var聲明的變數可以多次賦值 結論:能用let不用var ,因為作用域的問題 2.基本類型和對象類型 undefined 和 null undefined 指 未定義的對 ...
  • 代理模式(Proxy Pattern)是一種結構型設計模式,結構型模式描述如何將類或對象按某種佈局組成更大的結構。它允許你提供一個代理對象來控制對另一個對象的訪問。代理對象擁有與實際對象相同的介面,因此它可以被用來代替實際對象。 ...
  • 在軟體行業,對於什麼是架構,都有很多的爭論,每個人都有自己的理解。在不同的書籍上, 不同的作者, 對於架構的定義也不統一, 角度不同, 定義不同。此君說的架構和彼君理解的架構未必是一回事。因此我們在討論架構之前,我們先討論架構的概念定義, 因為概念是人認識這個世界的基礎和用來溝通的手段,如果對架構概... ...
  • 超級大的數做加減乘除 java有八大數據類型: 1、byte(位),最大存儲數據量是255; 2、short(短整數),最大數據存儲量是65536; 3、int(整數),最大數據存儲容量是2的32次方減1; 4、long(長整數),最大數據存儲容量是2的64次方減1; 5、float(單精度浮動數) ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...