特全的Java學習路線圖,值得收藏

程序員小樂 發佈 2020-03-08T16:56:05+00:00

Smile and stop complaining about the things you can't change. Time keeps ticking whether you're happy or sad.

點擊上方 "程式設計師小樂"關注, 星標或置頂一起成長

每天凌晨00點00分, 第一時間與你相約


每日英文

Smile and stop complaining about the things you can't change. Time keeps ticking whether you're happy or sad.

保持微笑,停止抱怨那些改變不了的事。無論你開心與否,時間總是不等人的。


每日掏心話

邂逅,像一水江頭逢了一片小舟,輕輕相望,又靜靜回眸,欸乃過後的山水綠,盪影重重,情愫雜聲,化作白天的眼眸,落在等待的心頭。


來自:Jabari |責編:樂樂

連結:jianshu.com/p/d51551b0a8ba

程式設計師小樂(ID:study_tech)第 797 次推文 圖片來自百度


往日回顧:用漫畫了解 Linux 內核到底長啥樣!


正文


Java是一個通用的程式語言,其實可以干很多事,怎麼學Java就看怎麼用了,但有一些一般的步驟:


  • 熟悉一種文本編輯器,比如Vim, Emacs, Notepad++, TextMate等。知道哪些是開源的,哪些是閉源的,哪些要收費。養成不用盜版軟體的習慣。

  • 安裝JDK(建議用你的Linux發行版自帶的軟體包管理器安裝openjdk,過程中可能需要讀發行版特定的文檔)

  • 寫一個Java的Helloworld程序,並用命令行工具javac編譯,再用java命令運行這個程序。過程中熟悉原始碼、字節碼、虛擬機這些東西,以及Java的包(package)對.class文件所在的路徑的影響。如果這兩個命令行工具使用熟練了,可以開始選一個喜歡的集成開發環境,比如Eclipse。當然,養成不用盜版軟體的習慣。熟悉一下如何建立「工程」,以及快捷鍵的使用。

  • 學習Java的面向過程編程,包括基本數據結構、表達式、語句、控制流、函數調用。

  • 學習Java的面向對象編程,包括類、引用類型和值類型的區別、成員、方法、訪問控制、繼承、多態、接口、接口實現。順便學習一下面向對象的基本思想,即對象、消息、封裝、繼承、多態等,這些通用的內容不是Java特有的。這時候應該已經涉及了Java的垃圾回收。要留意即使有垃圾回收的情況下也會發生的內存泄露(如自己設計數組容器,元素是引用,邏輯上刪除了元素,但並沒有清成null)。注意垃圾回收只能回收內存中的對象,除了內存以外,其它資源不能依靠垃圾回收來關閉。比如,文件、管道、Socket、資料庫連接等,垃圾回收是不會幫你關閉的。

  • 學習Java的異常處理,但更重要的是學習什麼時候用特殊返回值而不使用異常,什麼時候應該拋出異常而不處理異常,知道什麼是pokemon catch及其危害,了解為什麼Java的checked exception是一個糟糕的特性。如果願意,同時學習一下Java1.7的try-with-resource語句和AutoCloseable接口。

  • 熟悉Java常用的數據結構,如基本的數組類型,以及泛型容器(java.util.*),尤其是java.util.List接口和java.util.ArrayList實現;以及java.util.Map接口和java.util.HashMap實現。(java1.5以前的沒有泛型參數的就不用碰了)同時留意一下基本類型int, double等和裝箱類型Integer和Double的區別,以及它們是如何自動轉換的。

  • 熟悉Java標準庫里的各種工具,包括日期時間、字符串格式化、IO等。**知道文件要自己在finally子句中close(),或者用Java1.7的try-with-resource,不要妄想垃圾回收器會幫你關掉文件。

  • 學習一下Java的命名習慣,以及JavaBeans的常規,知道為什麼getter/setter比直接操作成員變量好。按這種方式給Java的變量、方法命名。同時看看你的IDE能不能自動幫你生成getter和setter。

  • 使用一個第三方的庫(比如Apache Commons Lang通用工具庫),讓你的程序依賴於它的二進位jar包(而不是直接拷貝原始碼),用命令行編譯、運行(注意classpath等);也熟悉一下如何用你的集成開發環境添加第三方依賴。感受一下手動管理依賴關係的麻煩。

  • 學習Maven的使用,試著讓Maven幫你解決依賴關係,再試著讓Maven幫你創建一個Eclipse工程。再試試用Maven打包發布。

  • 學習軟體測試,以及JUnit的使用,以及怎麼在IDE中使用JUnit。有空看一下coverage工具。

  • 讀讀四人幫寫的《設計模式》(這本書是用C++和Smalltalk語言為例子的,但仍然適合Java)。


接下來就看具體要做哪方面的應用了,看需求。比如(下面的沒有順序)


關於語言


  • 如果學Java學得不舒服了,學Python。

  • 如果對面向對象編程的概念有點不習慣,學Smalltalk。(Ruby也行,但不如Smalltalk經典。Ruby的文檔是一大硬傷。)

  • 如果嫌Java太囉嗦,學Python

  • 如果嫌Java太囉嗦,又想用JVM,自己又有精力,學Scala

  • 如果對對象之間的關係有點暈,學一學UML,以及它的一些圖,可以對程序和運行進行直觀的建模。你的IDE也許有插件可以生成UML圖。但是不要太沉迷於這些方法論。


調試和輔助工具


學習一下你的集成開發環境提供的調試工具,加一些斷點試試。


  • 試試用jconsole或者VisualVM監控另一個jvm的狀態。

  • 用profiling工具尋找程序中慢的地方。Eclipse有profiling工具。VisualVM也有這樣的功能。(如果不介意使用閉源軟體的話,也試試JProfiler和YourKit)

  • 有的JVM允許在運行時更新代碼。Eclipse可以和某些JVM集成。這樣你可以頻繁修改代碼而不用頻繁重啟JVM。對於某些「重型」工程很有用。(如果不介意使用閉源軟體的話,也試試jRebel)


多線程


學習Java的多線程編程以及lock、condition的用法(包括傳統Java的synchronized語句以及新加的java.util.concurrent.*),學習一下如何讓線程停下來,以及為什麼要頻繁確認isInterrupted()而不要用Thread.stop()。了解一下多核處理器、緩存、內存的關係,以及為什麼多線程編程這麼難。


  • 如果還舒服,學習一下Runnable的用法,以及自帶的Executer等基本多線程工具。

  • 應該已經留意到java.util裡面的很多容器不是線程安全的,但是java.util.Collections可以幫你創建一些安全的版本。另外關注一下java.util.concurrent裡面有ConcurrentMap等容器可供使用。

  • 如果有空的話,看看memory model(內存一致性模型)和無鎖同步(見java memory model和java.util.concurrent.atomic)。

  • 如果還有空,再了解一下除了「共享內存多線程編程」以外有沒有別的模型(多進程multi-processing、消息傳遞message passing等)。


反射、元編程


  • 學習Java的反射機制,以及Annotation的用法。

  • 如果還舒服,試試java.lang.reflect.Proxy的用法。

  • 如果仍然還舒服,玩一玩CGLib(一個第三方的庫)。


網絡編程


學習一下IP,TCP協議(計算機專業的應該學過,複習一下),學習Socket編程(注意垃圾回收器不會幫你關掉Socket)。


  • 如果不是很關心HTTP,看看java.nio,學習單線程輪詢式IO復用(Selector)。

  • 如果有點不明白nio的意圖的話,了解一下c10k問題。http://www.kegel.com/c10k.html

  • 如果身體沒有異樣的話,大概了解一下作業系統(包括C語言)提供的select, poll, epoll, kqueue等接口。

  • 如果身體仍然沒有異樣的話,試著用java.nio寫一個文件伺服器。

  • 如果還有精力的話,上網扒一扒有沒有其他的通信庫,如netty等。

  • 如果關心Web還有HTTP,就學習一下HTTP協議,以及用Java進行HTTP的客戶端編程。

  • 如果還舒服,學學HTML,寫寫HTML的靜態網頁(不需要Java)

  • 如果還舒服,用Java寫一個基於DOM、XPath或者CSS Selector的網頁解析器(爬網頁)。

  • 如果還舒服,學學Java的Servlet接口(先別學jsp)進行Web伺服器端編程。學學標準的Servlet容器怎麼用,包括web.xml的用法以及listener、filter等概念。以及某個Servlet容器(如Jetty或者Tomcat)的具體用法。

  • 如果仍然還舒服,試著學一種模板語言(如haml, velocity, freemarker,【還有其他更好的框架嗎?我不知道】, String.format,如果真的想學JSP的話JSP倒是也行,但不推薦)。

  • 如果仍然覺得舒服,學學Spring框架中的Web框架,或者Struts,看你的口味。

  • 如果還舒服,看看Spring Bean Container以及裡面各種亂七八糟的工具。

  • 如果還舒服,或者有需求,了解一下什麼是RESTful Web Service,複習一下HTTP,找找適合的Java工具。

  • 你可能會覺得Jackson是一個解析JSON用的好用的東西。


資料庫


學習一下關係資料庫(計算機專業的應該學過,複習一下),包括SQL。選一個資料庫管理系統熟悉一下(比如MariaDB,或者(如果你不討厭Oracle的話)用被Oracle收購了的MySQL。先脫離Java單獨學學)。然後看它們的官方文檔教你怎麼用Java連接這種資料庫。這中間會涉及到JDBC接口。同時一定要知道SQL注入安全漏洞,以及掌握如何用PreparedStatement防止注入!!。建議看 http://bobby-tables.com/


  • 可能中間會涉及「事務」問題,讓你不知不覺地開始去了解java transaction api(JTA)。

  • 如果還舒服,學一學對象關係轉換(如Hibernate)。

  • 也可以學學非關係資料庫,以及如何用Java訪問它們。


日誌記錄


學習一下slf4j和logback的用法。


  • 如果有精力的話,大概了解一下世界上有多少種Java日誌框架,以及slf4j是怎麼橋接這些框架的。


構建(build)系統


學習一下Ant的用法。


  • 如果還舒服的話,學習一下用Ivy從Maven的倉庫里下載軟體包,解決依賴關係。


版本控制


學習一種分布式版本控制器(如Git、Mercurial、Bzr、Darcs等,推薦Git)的基本用法,以及如何用它管理Java工程。希望你已經開始使用Maven了,並且知道為什麼把IDE生成的工程文件(如eclipse的.project,.classpath和.metadata)放入版本控制器不好。然後了解一下如何在IDE中使用版本控制(Eclipse自帶Git插件)。


  • 如果感覺很舒服的話,為你們實驗室搭建一個Linux+SSH+Git伺服器,裝個GitLab(一種Web介面)。

  • 了解「集中式版本控制器」和「分布式版本控制器」的區別,並說服同事們不要再用SVN、CVS或者SourceSafe等老舊的「集中式版本控制器」了。

  • 開設一個GitHub帳戶。如果你不喜歡Git,就用BitBucket等。


持續集成


自己(或者為你們實驗室)搭建一個持續集成(Continuous Integration)伺服器,如Jenkins,定期編譯你的程序。建議同時使用Git等分布式版本控制器。


  • 如果你做開源軟體,試試GitHub和Travis。


零碎工具


淘一淘java.nio.files裡面有什麼好用的東東,然後再淘一淘Apache Commons Lang和Commons IO里有什麼好用的工具。Commons Logging就不要再用了,用SLF4j和Logback。


XML


學學XML、DOM、XPath。XML這東西到處都可能用到。也可以用它寫自己的配置文件。


  • 如果覺得不舒服了,就學學JSON和YAML。

  • 如果還是不舒服,就學學文本文件解析。


語法分析和編譯器


學學Antlr或者別的Parser Generator的用法


  • 如果覺得舒服,自己寫一個計算器。

  • 如果還覺得舒服,自己寫一種Domain-Specific Language (DSL)。


高效容器


學學FastUtil或者Trove,如果你需要進行大量數值運算的話。


分布式計算


學學MapReduce的思想以及它的實現。


  • 如果還舒服,學學Scala語言以及號稱比MapReduce快得多的Apache Spark。


進程間通信


看看ActiveMQ、MINA和RMI。


其他語言(JVM)


學習另一門跑在JVM上的語言或者實現(如Groovy、Scala、Clojure、JRuby、Jython、JavaScript……)


  • 如果還舒服,學一學Java Scripting API(注意不是JavaScript。給個連結:http://docs.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/ ),然後試著在自己的Java程序里嵌入腳本。


其他語言(非JVM)


學習另一門通用腳本語言(如Python、Ruby,其實perl也行,但不推薦),知道什麼時候Java不是最好的選擇。


Java語言和Java虛擬機


通讀一遍(一目十行地讀,不用細讀)Java Language Specification,以及Java Virtual Machine Specification。


  • 了解以下解釋器(interpreter)、編譯器(compiler)、即時編譯器(just-in-time compiler)和優化器(optimiser)的概念。

  • 如果對編譯器的話題不感到畏懼,了解一下method JIT和tracing JIT的概念和區別。


內存管理


學學垃圾回收的幾種基本算法,包括mark-sweep、mark-compact、semi-space、generational、mark-region等,各自的性能,以及為什麼樸素的reference counting是不完整的。知道為什麼finalizer性能很糟糕,而且標準並不要求finalizer在程序退出前一定會執行。


  • 如果還舒服,了解一下如何設置Java虛擬機的堆大小限制(如HotSpot虛擬機的-Xmx選項等)。

  • 了解一下Java里的WeakReference以及SoftReference和PhantomReference,以及它們什麼時候有用,以及為什麼它們實現起來有些困難。

  • 如果有精力,了解一下Hotspot虛擬機的內存管理算法是什麼樣的。


動態裝載


學學Java的動態裝載(class loading)


  • 如果還舒服的話,學學OSGI以及它的一種實現(如Felix或者Equinox)

  • 如果仍然很舒服的話,學學寫基於Eclipse平台的程序。不是Eclipse集成開發環境,只是利用他們的圖形框架,寫自己的應用程式。

  • 如果還覺得舒服的話,寫Eclipse集成開發環境的插件。


本地/外語接口


學習一下Java Native Interface(JNI),試著寫一個Java和C語言混合編程的程序。


  • 如果覺得不舒服了或者覺得欲仙欲死,就學一學Java Native Access(JNA),試一試不用任何膠水代碼而從Java直接裝載C庫,直接調用C函數。

  • 如果連JNA也懶得學,就學一學SWIG,自動生成綁定。

  • 如果覺得舒服,就學一學Java Virtual Machine Tooling Interface(JVMTI),用C程序來監視JVM的狀態。


密碼學


學一學密碼學,包括編碼、密碼分析、攻擊、對稱密鑰、公鑰系統、數字簽名、哈希算法等,看看Java有沒有實現。


如果覺得有點不舒服(你應該不會覺得舒服吧,除非你是學密碼學的,要不然總會覺得自己寫的程序有安全漏洞),就寫一個「人品計算器」來放鬆一下,要求每次輸入同一個姓名,得到的人品值是固定的,但又要讓人無法用別人的人品值猜自己的人品值。


移動終端


學一學Android開發。


如果有精力的話,看看Dalvik虛擬機是怎麼回事。

建議買一個iPhone或者iPad,或許你再也不想用Android手機或者平板了。


歷史


如果覺得有些無聊,就去挖一挖歷史上比較火的可能和Java相關技術,比如:


  • Applet,想想它比起html5+css3+javascript的缺點在哪裡。

  • AWT、Swing,想想為什麼很少有人用Java寫圖形介面程序。你覺得Swing的程序看上去舒服嗎?中國人和殘疾人喜歡用Swing程序嗎?

  • JNDI,想想它比起Spring Bean Container的缺點在哪裡。

  • JSP,想想它比起MVC結構的缺點在哪裡。

  • WSDL/SOAP,把它們和XML-RPC、RESTful Web Service比較一下。

  • XSLT,以及為什麼它是圖靈完備的。可是它真的比Java本身更好用嗎?

  • Log4j、java.util.logging、Apache Commons Logging,各自有什麼問題,以及Log4j的作者本人為什麼又開發了SLF4j和Logback?

  • Java最早是為什麼設計的?

  • Type erasure是怎麼回事?為什麼ArrayList<int>不行但ArrayList<Integer>就可以?挖一挖歷史。


其實Java不算完全面向對象的語言。Java更偏實用性,很多控制流(if語句、while循環、for循環等)來自面向過程的語言;基本數據類型(int, char, double等)也不是對象。但另一些語言,比如SmallTalk,更偏向純粹的面向對象的設計,包括基本的數據類型都是對象,if/while/for等也用對象和方法來實現。比如:


基本數據類型也是對象,可以接受消息(即方法),比如:


(a + b) sqrt


這裡面,a+b其實是向a發送「+」消息,參數是b。sqrt也是一個消息,發給一個數。


if分支是這樣做的:


(x < y) ifTrue: [

max := y.

i := j

] ifFalse: [

max := x.

i := k

]


ifTrue:ifFalse: 是一個Boolean對象的一個方法,取兩個參數,每個是一個「塊」,分別在真和假的情況下執行。


還有while循環是這樣做的:


[i < 100] whileTrue: [

sum := sum + i.

i := i + 1

]


whileTrue是「塊」的一個方法,每次對塊求值,如果是真,就反覆執行第一個參數(也是「塊」)。


所以,相對其他面向對象的語言,Java並不算很「面向對象」。所以需要補充一些對面向對象語言的了解。


歡迎在留言區留下你的觀點,一起討論提高。如果今天的文章讓你有新的啟發,學習能力的提升上有新的認識,歡迎轉發分享給更多人。


猜你還想看


阿里、騰訊、百度、華為、京東最新面試題匯集

你能說出多線程中 sleep、yield、join 的用法及 sleep與wait區別嗎?

一張圖理清 Vue 3.0 的響應式系統

這回把Spring @Async徹底搞懂了

關注訂閱號「程式設計師小樂」,收看更多精彩內容
嘿,你在看嗎?

關鍵字: