




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
Java
虛擬機基礎教程
目錄
第1章Java虛擬機
1.1JVM實現
1.2為何要在JVM上開發
1.2.1JVM適應市場的變化
1.2.2Java類庫
1.2.3生態系統
1.3常見的用途
1.3.1Web應用程序
1.3.2大數據
1.3.3IoT
1.4JVM概念
1.4.1虛擬機
1.4.2JIT編譯器
1.4.3基本數據類型
1.4.4類
1.4.5引用類型
1.4.6垃圾收集器
1.4.7向后兼容
1.4.8構建工具
1.5Java版本
1.5.1JavaSE
1.5.2JavaEE
1.5.3JavaME
1.6其他JVM語言
1.6.1為何選擇其他語言
1.6.2在同一個項目中使用多種JVM語言
1.6.3使用另一種語言編寫單元測試
1.7小結
第2章Java虛擬機開發
2.1JDK
2.1.1安裝JDK
2.1.2探索JDK
2.1.3JRE
2.2使用包組織類
2.2.1包是什么
2.2.2選擇包名
2.2.3包名舉例
2.2.4全限定類名
2.3Java類庫
2.3.1Java類庫的組織結構
2.3.2包概述
2.3.3java,lang包中的重要類
2.3.4集合APIjava.util.ArrayList和java.util.HashMap
2.4從命令行運行JVM應用程序
2.4.1至少有一個類包含靜態方法main。
2.4.2存儲類文件的Fl錄結構
2.4.3為JVM實例設置ClassPath
2.4.4將類文件放在JAR歸檔文件中
2.4.5使用命令java運行程序
2.4.6在JVM中運行的示例項目
2.5EelipseIDE
2.5.1下載EclipseIDE
2.5.2安裝EclipseIDE
2.6小結
第3章Java
3.1Java中的面向對象編程功能
3.1.1定義類
3.1.2類訪問限定符
3.1.3類限定符final——鎖定類
3.1.4定義包
3.1.5導入類
3.1.6添加類成員變量和方法
3.1.7限定符
3.1.8構造函數和終結方法
3.1.9向上轉換和向下轉換
3.2編寫Java代碼
3.2.1運算符
3.2.2條件檢查
3.2.3POJO
3.2.4數組
3.2.5泛型
環
循
3.2.6
常
異
3.2.7
程
線
3.2.8
3.2.91ambda
3.3編程風格指南
3.4小測驗
3.5小結
第4章Java編程
4.1配置EclipseIDE
4.2使用Java創建Web服務
4.2.1在EclipseIDE中新建Gradle項目
4.2.2修改Gradle構建文件
4.2.3構建項目
4.2.4編寫后端類
4.3小結
第5章Scala
5.1安裝Scala
5.2Scala的REPLshell
5.3函數式編程和命令式編程
5.4Scala語法和規則
541靜本舉型語言
5.4.2可修寶的變量和不可修改的變量
5.4.3常用的Scala類型
5.5Scala的OOP功能
5.5.1定義包和子包
5.5.2導入成員
5.5.3定義類
5.5.4實例變量和實例方法
5.5.5構造函數
5.5.6擴展類
5.5.7重載方法
5.5.8抽象類
5.5.9特質
5.5.10單例對象
5.5.11運算符重載
5.5.12Case類
5.6Scala標準庫
5.6.1泛型
5.6.2集合
5.6.3XML處理
5.7Scala的函數式編程功能
5.7.1使用函數遍歷集合
5.7.2映射-過濾-歸約設計模式
5.7.3柯里化
5.8小測驗
5.9小結
第6章Scala編程
6.1ScalaIDEforEclipse插件
6.1.1安裝ScalaIDEforEclipse
6.1.2切換到ScalaIDE透視圖
6.2SBT
6.2.1安裝SBT
6.2.2創建基于SBT的EclipseIDE項目
6.2.3Scala編譯器(scalac)
6.3創建Akka項目
6.3.1在SBT構建文件中添加Akka依賴項
6.3.2更新ScalaIDE項目
6.3.3Akka概念
6.3.4創建第一個AkkaActorQuotesHandlerActor
6.3.5創建消息
6.3.6編寫基于ScalaTest的單元測試
6.3.7實現消息處理程序
6.3.8創建QuotePrinterActor
6.3.9主應用程序
6.4小結
第7章Clojure
7.1安裝Clojure
創建啟動腳本
7.2Clojure的交互式shell(REPL)
7.3Clojure語言
7.3.1語法
7.3.2表達式
7.3.3定義變量
7.3.4定義函數
7.3.5數據結構
7.4使用Java類
使用deftype和defrecord創建簡單的Java類
7.5使用代理管理狀態
代理示例
7.6風格指南
7.7小測驗
7.8小結
第8章Clojuro編程
8.1EclipseIDE插件Counterclockwise
8.1.1安裝插件Counterclockwise
8.1.2切換到Java透視圖
8.2構建工具Leiningen
安裝Leiningen
8.3創建可執行的Clojure程序
8.3.1在不使用Leiningen的情況下將代碼編譯成類文件
8.3.2使用Leiningen編譯項目
8.4新建Counterclockwise項目
8.4.1EclipseIDE中的ClojureREPL
8.4.2更新項目的Clojure版本
8.4.3添加依賴
8.5以測試驅動開發的方式探索monad
8.6Web框架Luminus
8.6.1創建Luminus項目
8.6.2將項目導入Counterclockwise
8.6.3探索Luminus項目
8.6.4在Web應用程序中添加頁面
8.7小結
第9章Kot1in
9.1安裝Kotlin
啟動腳本
9.2Kot1in的REPL交互式shell
9.3Kotlin語言基礎
9.3.1定義局部變量
9.3.2定義函數
9.3.3Kotlin類型
9.3.4循環
9.4Kotlin的OOP功能
9.4.1定義包
9.4.2導入成員
9.4.3定義類和構造函數
9.4.4給類添加成員
9.4.5繼承
9.4.6接口
9.4.7可見性限定符
9.4.8單例對象和伴生對象
9.4.9數據類
9.4.10lambda和內聯函數
9.5Kotlin過程性編程
9.6風格指南
9.7小測驗
9.8小結
第10章Kotlin編程
10.1EclipseIDEKotlin插件
10.1.1安裝EclipseIDEKotlin插件
10.1.2切換到Kotlin透視圖
10.2ApacheMaven
10.2.1安裝ApacheMaven
10.2.2下載預制的Kotlin基本套件
10.2.3在EclipseIDE中導入項目
10.2.4探索構建文件pom.xml
10.2.5在Eelipse中更新構建文件
10.3創建JavaFX桌面GUI應用程序
10.3.1定制項目
10.3.2創建可運行的應用程序
10.3.3編寫擴展函數
10.3.4布局窗格
10.3.5實現基干BordorPane的布局
10.3.6實現動畫
10.3.7調試程序
10.4小結
第II章Groovy
11.1安裝Groovy
GroovyConsole和GroovyShell
11.2Groovy語言
Groovy面向對象編程
11.3Groovy開發包(GDK)
11.3.1Groovy字符串(GString)
11.3.2集合
11.4動態和靜態編程
11.4.1元編程
11.4.2Groovy靜態編程
11.5小測驗
11.6小結
第12章Groovy編程
12.1安裝GroovyEclipse插件
切換到Java透視圖
12.2ApacheIvy和IvyDE
安裝用于EclipseIDE的ApacheIvyDE插件
12.3創建并配置項目
12.3.1新建GroovyEclipse項目
12.3.2創建供Ivy使用的ivy.xml文件
12.4JavaDatabaseConnectivity(JDBC)
12.4.1H2數據庫
12.4.2創建內存數據庫
12.5使用MarkupBuilder生成XML
根據SQL查詢結果生成XML
12.6微服務平臺Vert,x
12.6.1在文件ivy.xml中添加Vert.x依賴
12.6.2創建Web服務
12.7小結
附錄A其他JVM語言
A.1OracleNashorn
A.1.1在基于JVM的項目中嵌入Nashorn
A.1.2運行Nashorn
A.2Jython(Python)
A.2.1CPython和Jython的不同之處
A.2.2運行Jython
A.3JRuby(Ruby)
A.3.1RubyonRails和JRuby
A.3.2運行JRuby
A.4Frege(Haskel1)
A.4.1在Frege中調用Java代碼
A.4.2運行Frege
A.5Ceylon
A.5.1Ceylon的模塊系統
A.5.2運行Ceylon
A.6小結
附錄B小測驗答案
第1章Java虛擬機
Java虛擬機(JavaVirtualMachine,JVM)是一個可用于開發和部署軟件的現代平臺。顧名
思義,最初開發它旨在支持使用Java語言編寫的應用程序,但設計Java的人不久就認識到,
JV.M不僅可運行Java語言,還可利用Java的功能和龐大的類庫。
1995年,Sun公司1發布了Java和第一個JVM實現。鑒于其重點是網絡應用程序,Java很快
就大行其道;它還被設計成可隨處運行。開發Java的初衷是用于機頂盒編程,但Sun公司發
現彼時機頂盒市場還不成熟,因此決定同時將這個平臺推向臺式機。為此,Sun公司設計了一
種獨特的二進制可執行格式,并稱之為Java字節碼。要運行被編譯成Java字節碼的程序,系
統必須安裝JVM實現。
iSun公司于2009年4月被Oraele公司收購。一一編者注
本書將簡要地介紹5種最流行的JVM語言。通過學習這些語言的基礎知識,并動手編寫代碼,
你將能夠做出判斷,確定哪種語言對你、你的團隊和項目來說是最合適的。
我們先來說點實在的,到第2章再深入介紹Java開發包(JDE)和Java類庫,當前,可使用
的編程語言和平臺眾多,它們相互爭奪市場,因此有必要先來詳細地說說JVM向開發人員提供
了什么。有鑒于此,本章將介紹如下主題:
?為何要在JVM上進行開發;
?JVM的常見用途;
?JVM概念簡介;
?Java版本;
?其他JYM語言。
1.1JVM實現
需要指出的是,本書只考慮與OracleJavaSE8(和更高版本)兼容的實現。這個版本
可在臺式機、服務器和眾多單板計算機(包括尺寸如信用卡的所有RaspberryPi)上安裝。
本書使用的是Oracle的JVM實現,你也可使用開源的OpenJDK和IBM的J9JavaSE實現。
本書不涵蓋Google發布的用于Android手機和平板電腦的Java平臺,因為用于Android的
Java版本基于較舊的Java版本。雖然用于Android的Java平臺版本越來越新,但它并未提
供Orac"JavaSE8的所有功能,且需要使用不同的編譯器和工具八另外,Gccgla刪除了大
量的JavaSEAPI,取而代之的是Google自己開發的不兼容的API。然而,本書介紹的有些語
言也可用于Android開發。例如,Kotlin就是一種非常流行的Android開發語言,但本書不
會龍此展開討論。
1.2為何要在JVM上開發
當前,可供使用的編程語言和平臺眾多,為何要在JVM上開發和部署項目呢?因為JVM最初是
為Java語言開發的,而近年來,其他語言的擁是無數次地宣稱,Java語言已過時乃至死亡。
近年來,流行的編程語言如走馬燈似的更換,而Java猶如常青樹,始終處于全球使用最多的
編程語言排行榜的前列。
JVM平臺為何如此強大呢?下面來看看其中一些最重要的原囚:
?它適應市場的變化,從而確保與時俱進:
?內置的Java類庫非常強大;
?它有無可比擬的生態系統。
1.2.1JVM適應市場的變化
Java于20世紀90年代中期面世,那時的計算機裝備的都是單核CPU,內存量也沒有兒個GB,
因為內存條貴得不得了。Java是與時俱進的語言之一:多核CPU面世后不久,Java就通過在
多個線程中運行代碼來支持多核,但它并沒有就此止步,而是在每次推出新版本時,都添加了
讓并發編程更容易的新類。這種做法到現在依然沒有停止。
函數式編程范式大行其道后,Java在核心語言中新增了對1alibda和流的支持。雖然Java提
供這種支持的時間很晚,但相比于其他流行的語言,其實現更佳。這是因為程序員幾乎什么都
不用做就能實現多線程。
適應市場變化還意味著有時需要做減法。Java面世時,熱點是直接在瀏覽器中運行Java代碼。
這些微型程序被稱為applet,要求瀏覽器和系統安裝專用的瀏覽器插件。而現在,市場已將
JavaScript作為創建交互式網站的標準語言。有鑒于此,Oracle最近摒棄了aDDlet標準。
1.2.2Java類庫
在每個Java版本(這將在本章后面更詳細地介紹)中,都指定了相應的JVM實現必須提供哪
些類。JavaSE8的類庫包含大量的類,每個遵循JavaSE8平臺標準的JVM實現都必須實現
這些類,而不管這種實現是由誰開發的。
這個類庫中的類提供了諸如讀寫控制臺窗口、執行文件I/O以及與TCP服務器進行通信等功能,
還有很多用于啟動和管理操作系統線程的類。更重要的是,還包含定義列表和映射(在有些語
言中稱為字典)等眾多數據結構的類。下一章將詳細介紹Java類庫中的類。
Java類庫是語言設計人員將JVM作為目標開發平臺的重要原因之一。有了這個類庫定義的數
據結構后,他們能夠史專注于語言設計,而不用太專注于從頭開始打造完整的運行時庫。要知
道,打造能夠與Java類庫媲美的、經過全面測試的、多平臺運行時系統類庫可是一項艱巨的
任務。
1.2.3生態系統
顯然,內置的類庫不可能涵蓋程序員的所有用例。對于內置類庫缺失的東西,可求助于其他公
司、組織和個人開發的庫和工具,以節省開發時間。鑒于很多年來Java都非常成功,其生態
系統是無可比擬的,因此很難找到一個這樣的平臺,即其中可供選擇的工具、庫、工具包和框
架比JVM提供的還要好。
鑒于可供使用的插件庫眾多,開發人員的開發方向幾乎不會受到Java的限制。為說明Java
生態系統有多豐富,我們來看看創建Web應用程序時,Java開發人員通常具有的選擇空間:
?創建在JVM應用程序服務器中運行的Web應用程序;
?為快速獲得結果,可使用通用的高級Web框架;
?為獲得更大的控制權,可使用微服務框架來創建應用程序。
場景L使用JVM應用程序服務器
開發人員可以像企業那樣安裝基于JV'M的應用程序服務器(這可以是開源的,也可以是付費的
專用服務器),并使用它來運行應用程序和Wob應用程序。這種服務器將負責處理配置問題以
及管理數據庫連接。
有簡單的應用程序服務器,它們只包含運行基本Web應用程序所需的內置API。但也有經過
Oracle認證的功能齊備的應用程序服務器,它們提供了大量內置的標準化API,其中包括訪問
數據庫的API、生成或使用XML和JSON文檔的API、按SOAP或REST標準與其他Web服務通信
的API、確保Web安全的API、向遺留計算機系統發送消息或從這些系統接收消息的API等。
下面是兩個最重要的企業開發框架:
?OracleJava企業版(JavaEE)平臺,這將在本書后面介紹;
?Spring框架生態系統(其中包括SpringBoot)<,
很多應用程序都結合使用了這兩種技術。
下面是一些流行的應用程序服務器:
?ApacheTomcat(用于運行簡單的Web應用程序);
?ApacheTomEE:
?RedHatWildFly;
?OracleGlassFish;
?RedHatJBossEnterpriseApplicationPlatform;
?OracleWebLogico
其中前四個是開源的,而后兩個是專用的。
場景2:使用高級的通用Web應用程序框架
第二種選擇是使用完整的Web應用程序框架。相比于企業框架,這些框架提供的API通常更高
級,它們還提供了內置的模型-視圖-控制器(model-view-controller,MVC)解決方案,可極
大地提高開發人員的效率。
使用這些框架時,開發人員的選擇通常受到限制,因為它們只支持為數不多的幾個庫和工具包。
然而,它們支持添加插件來提供其他選擇。換而言之,使用這些框架是以放棄一些選擇空間來
換取更短的開發周期。有些框架要求應用程序運行在JVM應用程序服務器中,而有些提供了自
己的HTTP服務器。
在這種框架中,ApacheStruts一度非常流行,但現在最流行的可能是Play。
場景3:使用微服務框架
另一種選擇是使用現代微服務框架來創建應用程序。這些框架提供了內置的HTTP服務器,可
用于運行應用程序,但沒有提供其他任何現成的工具和庫。在這種情況下,更容易根據需要混
合使用不同的庫和工具包。
為了采用現代微服務架構,通常將應用程序分成多個獨立的Web服務,但這些框架并不要求你
必須這樣做。
最常用的微服務框架包括Vert,x和SparkJava,其中后者并非是用于ApacheSpark大數據
平臺的。
1.3常見的用途
前面提供了一些證據,證明了JVV是切實可行的現代軟件開發平臺,下面來看看一些常見的
JVM用途:
?呢b應用程序;
?大數據分析;
?物聯網。
1.3.1Web應用程序
非常重視性能,很多人都選擇使用它來開發Wob應用程序。在設計正確的情況下,應用程
序在需要跨越眾多不同服務器時的伸縮性極佳。
JV'I是一個大家了解得非常清楚的平臺,這意味著其行為是可預測的。另外,它還提供了很多
T具.可用來調試和剖析有問題的應用程序°鑒于JVM是開源的,完全可以對其內部進行監視.
對那些必須同時為數以千計的用戶提供服務的Web應用程序來說,這是一個非常重要的優點。
JVV在云計算中扮演著重要的角色。Twitter>Amazon、Spotify和Netflix等很多著名公司都
在其基于云的服務的核心部分使用了JVNU
1.3.2大數據
大數據是當前的一個熱點。在數據太大,尢法使用傳統的數據庫進行分析時,可搭建多個數據
庫集群來處理它們。大數據分析包括查找特定的信息、找出規律、計算統計指標等。
這種數據可能是從Web服務器收集的數據(如已登錄用戶的單擊)、位于制造車間的外部傳感
器的輸出、遺留服務器多年來生成的日志文件等。它們的規模各不相同,但通常多達數TB。
下面是大數據領域兩種流行的數據分析技術。
?ApacheHadoop:負責存儲數據以及將數據分發到其他服務器。
?ApacheSpark:使用Hadoop對數據進行流化(stream),以便能夠對到來的數據進行分
析。
Hadoop和Spark都主要是使用Java編寫的。它們都提供了接口,以支持大量的編程語言和平
臺,其中當然包括jVMo
函或式編程蔡式致力于。創建可在多個CPU內核中安全運行的代碼,因此進行Spark或Hadoop
編程時,Scala和Clojure等純函數式編程語言是非常合適的選擇。
1.3.3IoT
當前,能夠連接到Internet的移動設備非常普及。鑒于Java最初就是為在嵌入式設備中運行
而設計的,因此在IoT領域,JVM也處于優勢地位。
對于內存有限的系統,Oracle提供了JavaMEEmbedded平臺。這種平臺是專門為不需要標準
圖形(或基于控制臺的)用戶界面的商用IoT設備設計的。
對于那些內存還算寬裕的設備,可使用JavaSEEmbedded版。JavaSEEmbedded與本書討論
的JavaSE很像,在運行完整Linux的環境中,可使用它來提供桌面GUI,以支持全面的用戶
交互。
JavaMEEmbedded和JavaSEEmbedded平臺都能夠訪問RaspberryPi的通用輸入/輸出
(general-purposeinput/output,GP10)針腳,這意味著可通過Java代碼來訪問這些端口
連接的傳感器和其他外圍設備。
1.4JVM概念
要有所作為,JVM開發人員必須熟悉下面這些最重要的JVM概念:
?JVM是一種虛擬機:
?JVM實現大都自帶即時(just-in-time,J1T)編譯器;
?JVM提供了一些內置的基本類型;
?除基本類型之外的其他一切都是對象;
?對象是通過引用類型來訪問的;
?垃圾收集器(garbagecollector,GO進程將過期的對象從內存中刪除;
?JVM大量地使用構建工具。
1.4.1虛擬機
Java虛擬機是一種虛擬機,這一點顯而易見,但必須牢記在心。這意味著從理論上說,在一
種計算機上開發的應用程序,可在另一種計算機上運行。
一般而言,代碼在32位壞是64位的Java運行時環境(JavaRuntimeEnvironment.JRE)U」
運行無關緊要。在64位的運行時環境中運行時,應用程序可使用的內存可能更多,但只要應
用程序不執行原生操作系統調用或需要數GB的內存,這種差別就無關緊要。
在C等語言中,數據類型的長度取決于原生系統,而Java不存在這樣的問題或特色(這
是問題還是特色取決于你怎么看)。在JVM中,整型都是無符號的且長32位,而不管運行程
序的是哪種計算機平臺或系統架構。
最后,需要指出的是,在JVM中運行的每個應用程序都在系統內存中加載自己的JV”實例。這
意味著同時運行多個Java應用程序時,每個應用程序都有自己的JVM副本;這還意味著在必
要的情況下,不同的應用程序可使用不同的JVM版本。出于安全考慮,不建議在同一個系統中
安裝不同的JDK或JRE版本;通常最好只安裝系統支持的最新版本。
1.4.2JIT編譯器
雖然沒有規定,但所有流行的JVM實現都并非只有簡單的解釋器:除解釋器外,它們還自帶了
復雜的JIT編譯器。
啟動Java應用程序時,將首先啟動并初始化JVM。JVM啟動并初始化后,它將立即開始解釋并
運行Java字節碼。在合適的情況下,解釋器將對程序的某些部分進行編譯,再將原生可執行
代碼加載到內存中,并開始執行這些代碼而不是經過解釋后的Java字節碼。這樣生成的代碼
的執行速度通常要快得多。
對代碼進行編譯還是解釋取決于很多因素。對于經常被調用的例程,JIT編譯器很可能對其進
行編譯以生成原生代碼。
JIT方法的優點在于,分發的文件可以是跨平臺的,且用戶無需等待整個應用程序編譯
完畢。JVM初始化后,應用程序將立即開始執行,而優化是在幕后完成的。
1.4.3基本數據類型
JVV提供了幾個內置的基本數據類型,這是Java未被視為純粹的OOP語言的主要原因。這些
類型的變量不是對象,且始終都包含值。
Java名稱描述和長度取值范圍(含)
byte有符號字節(ft位)-12R'127
short有符號短整型(16位)-32768"32767
int有符號整型(32位)-2「2"T
long有符號長整型(64位)-2“~2"T
float單精度浮點數(32位)不精確的浮點值
double雙精度浮點數(64位)不精確的浮點值
char單個UnicodeUTFT6字符(16位)Unicode字符0飛55535
boolean布爾值True/False
請注意,并非所有JVY語言都支持創建基本類型變量,并將其他一切都視為對象。你將看到,
這通常不是問題,因為Java類庫包含包裝基本類型的包裝對象,而包含Java在內的大多數語
言都會在必要時自動使用這些包裝對象。這個過程被稱為自動裝箱(auto-boxing)。
1.4.4類
函數和變量都是在類中聲明的。即使是應用程序的入口函數(在程序后動時例用的函數main。)
也是在類中聲明的。
JV"只支持單繼承模型,即類最多繼承一個類。這影響不大,因為使用了名為“接口”的結構
來緩解這種影響,你將在下一章看到。接口基本上是一個函數原型(只有函數的定義,而沒有
代碼)和常量列表,編譯器要求實現了接口的類必須提供這些函數的實現。類可實現任意數量
的接口,但必須提供這些接口定義的每個方法的實現。
本書介紹的有些語言對開發人員隱藏了上述事實。例如,不同于Java,有些語言允許
在類聲明外面定義函數和變量,甚至允許可執行代碼位于函數定義外面。還有些語言支持繼承
多個類。在內部,這些語言巧妙地規避了JVM的限制和設計決策。
JVV類通常以包的方式進行分組。在下一章,你將看到類是如何組織的。
1.4.5引用類型
與大多數現代編程語言一樣,JVM不直接操作指向對象的內存指針,而使用引用類型。引用變
量要么指向特定的類實例,要么什么都不指向。
如果一個引用變量指向特定的對象,就可使用它來調用該對象的方法或訪問其公有屬性。
如梟一個引用變量沒指向任何東西,就被稱為空引用(nullreference)。使用空引用來調用
方法或訪問屬性時,將在運行階段引發錯誤。對于這個常見的問題,本書介紹的有些語言提供
了解決方案。
引用和空引用
請看下面的代碼:
Prodtctp=nowProduct。;
p.selName("Boxofbiscuits*):
假設這里的Product是當前程序可使用的一個類。我們創建一個Product實例,并讓變量)
指向它。接下來,我們對這個對象實例調用方法setName。
NV沒有提供直接訪問這個Product對象所在內存單元的途徑,而只提供了指向該對象的引用。
當你使用變量P時.,JVM將確定為訪問這個變量指向的對象,需要訪問哪個內存單元。
我們在前述代碼片段中添加如下代碼行:
p=null;
p.setName("Thislinewillproduceanerroratrun-time");
可顯式地將引用設置為null。請注意,對于在方法內聲明的變量,并非必須這樣做,因為方
法結束時,將自動清理這些變量,但這樣做也是完全合法的。現在變量p是一個空引用。下一
段將介紹對象實例不再被任何引用變量指向后將發生的事情。
上述代碼能夠通過編譯,但程序運行時,最后一行將引發NullPointerException異常。女「果
沒有提供錯誤處理功能,應用程序將崩潰。很多現代IDE都力圖發現這種情形,并向開發人員
發出警告。
1.4.6垃圾收集器
JVM小要求程序員在創建和銷毀對象時手工分配和樣放內存塊。通常,程序員只需在需要時創
建龍象即可。
有一個名為GC的進程,它每隔一段時間讓應用程序停止執行,并在內存中掃描不再在作用域
內的對象(不能被任何對象訪問的對象),再將這些對象從內存中刪除,并收回釋放的內存空
間。
以前,這個進程會導致嚴重的性能問題,但它使用的算法已得到極大的改進。另外,根據應用
程序的需求,系統管理員可配置GC的眾多參數,以更好地控制它。
開發人員應始終牢記GC算法。如果你不斷地創建大量的對象,并確保它們位于作用域內(即
讓所有這些對象都是可訪問的,如將它們存儲在應用程序可訪問的列表中),那么遲早會導致
內存耗盡,進而引發錯誤。
示例
假設你為一個在線商店開發了一個電子商務應用程序,同時假設每位已登錄的用戶都有一個
ShoppingBasket實例,其中存儲了該用戶已加入到購物車中的商品。
現在假設今天有一位已登錄的用戶,他打算購買一塊香皂和一盒餅干。對于這位用戶,應用程
序將創建兩個Product實例(每件商品一個),并將它們添加到ShoppingBasket的products
列表中,如下圖所示。
結賬前,這位用戶發現Amazon也有這樣的餅干,但價格低得多,因此決定將其從購物車中刪
除。從技術上說,應用程序將從products列表中刪除相應的Product實例。但這樣做后,表
示Chocolatecookies的Product實例就成了孤兒對象。鑒于沒有任何引用指向它,應用程序
再也無法訪問它,如下圖所示。
過段時間后,JVM的GC啟動,它發現應用程序無法訪問表示Chocolatecookies的Product
對象,因此決定將其刪除,從而釋放它占用的內存,如下圖所示。
為避免GC將對象刪除,有多種技巧。其中一個著名的技巧是,在應用程序需要使用大量類似
的充象時,將這些對象放在一個對象池(對象列表)中。在應用程序需要對象時,只需從池中
取回一個,并根據需要修改它。使用完畢并不再需要該對象時,將其放回到對象池中。由于這
些充象始終在作用域內(未用時.,這些對象位于應用程序能夠訪問的對象池中),GC不會銷
毀它們。
1.4.7向后兼容
負責維護JVM和Java類庫的人深知企業開發人員的需求:現在編寫的代碼最好以后也能運行。
在向后兼容方面,JVM做得很不錯;如果你熟悉Python2和Python3,就知道情況并非總是
如此。
較新的JVM版本能夠運行針對較舊的JVM版本編譯的應用程序,條件是應用程序沒有使用在較
新的JVM版本中已刪除的API或技術。例如,在Java8JVM實例上運行的項目可加載并使用
針店Java6編譯的庫,但反過來行不通,即在Java6JVM實例上運行的應用程序不能加載針
對更高版本編譯的類。
當然,與其他平臺和語言一樣,負責維護JDK和Java類庫的人必須時小時地搟棄一些類和技
術。在向后兼容性方面,JVM雖然存在問題,但總體而言比眾多其他的平臺和語言要好得多。
另外,通常僅當有合適的替代品后,才會將API刪除。
1.4.8構建工具
在項目比較簡單的年代,為自動化編譯和打包過程,使用的是簡單的批文件或操作系統Shell
腳本文件。隨著項目越來越復雜,定義這樣的腳本越來越難。另外,對于不同的操作系統,必
須編寫完全不同的腳本。
不久后,第一套專用的Java構建工具應運而生。它們使用的是XML構建文件,讓你能夠編寫
跨平臺的腳本。最初,必須編寫冗長而繁瑣的腳本;但后來,這些工具采用了約定優先于配置
的范式。遵循這些工具指定的約定時,需要編寫的代碼少得多;但如果你面對的不是默認情形,
可能需要花很大的精力來讓工具按你希望的做。為自動化構建過程,較新的工具放棄了XM)
文件,轉而提供了腳本語言。
在這些工具中,很多都提供了如下功能。
?內置的依賴管理器:能夠從著名的網絡倉庫下載附加庫。
?自動運行單元測試,并在測試失敗時停止打包。
JDK本身沒有提供構建工具,但幾乎每個項目都至少使用了下面一個開源的構建自動化匚具。
?ApacheAnt(沒有內置的依賴管理器,使用的是基于XML的構建腳本)。
?ApacheMaven(通過使用XML文件引入了約定優先于配置的原則,并使用插件)。
?Gradle(構建腳本是使用Groovy或Kotlin編寫的)。
只要使用的是流行的IDE,JVM程序員就無需過多地考慮構建自動化工具,因為所有IDE都能
夠生成構建腳本。如果要獲得更大的控制權,可手工編寫腳本,并讓IDE根據你編寫的腳本來
編譯、測試和運行項目。
1.5Java版本
Java有多個不同的版本,其中每個版本都針對不同的用例。多年來,有些版本的名稱發生了
翻天覆地的變化,當前版本的名稱如下:
?Java標準版(JavaSE)
?Java企業版(JavaEE)
?Java微型版(JavaME)
1.5.1JavaSE
這是最重要的版本,大家說到Java時,通常指的是就是這個版本。本書只考慮JavaSE平臺。
這個版本用于臺式機利服務器。另外,你將看到,還有一個嵌入式版本,用于Raspberry"
的Linux發行版就自帶了這種嵌入版本。JavaSE自帶了完整的Java類庫,還包含經典的Swing
GUI工具包,而大多數版本還包含較新的JavaFXGUI工具包。
注意:較新的JavaSEEmbedded更新刪除了JavaFX工具包。在RaspberryPi上安裝
這個更新后,JavaFX組件將消失。Oracle以開源的方式提供了用于RaspberryPi的JavaFX,
讓高階用戶能夠下載并編譯它。
JavaSE主要用于創建獨立的控制臺應用程序、桌面GUI應用程序和無界面(headless)應用
程序,還可用于創建外部庫。
1.5.2JavaEE
JavaEE建立在JavaSE的基礎之上,因此要求安裝JavaSE。它添加了類型眾多的API。Java
EE應用程序通常運行在JVM應用程序服務器上。本書不會深入介紹JavaEE,但時不時會提及
它,因為它是Java平臺的重要補充,對企業開發人員來說尤其如此。
Oracle網站沒有提供獨立的JavaEE版本,你必須下載與所需JavaEE平臺版本兼容的應用
程序服務器。有些IDE也自帶了JavaEE應用程序服務器,這將在下一章討論。
JavaEE標準只描述了必須提供的APT,而沒有指定實現方式。具體如何實現符合標準的API,
由與JavaEE兼容的應用程序服務器決定。
示例:兩款應用程序服務器實現的Java持久化API
JavaEE描述了Java持久化API(JavaPersistenceAPT,JPA)<,這是一個對象關系映射器
(objectrelationmapper,ORM)API,位于Java對象和關系型數據庫(通常是SQL數據庫,
如Oracle、OracleMySQL、PostgreSQL等)之間;使用它只需編寫幾行代碼,就可將JVM對
象的內容寫入數據庫,反之(從數據庫讀取數據并將其加入對象中)亦然。
Oracle提供的JavaEE參考實現是一個開源的應用程序服務器,名為GlassFish。GlassFish
包含開源項目EclipseLink,該項目實現了JPA標準。RedHat出品的WildFly也是一款開源
的JavaEE應用程序服務器,其中包含RedHat自己開發的ORM開源項目Hibernate,這個項
目也實現了JPA標準,但更流行。
如果只使用JPA標準規定的功能,則使用哪種實現無關緊要,但要使用其他功能,選擇使用哪
種實現就很重要。
如果你不喜歡某個應用程序服務器廠商的設計決策,通常可轉而使用其他實現。對于
選擇空間,JVM開發人員非常在乎!
1.5.3JavaME
在iOS和Android面世前,JavaME是重要的功能手機和智能手機游戲和應用程序開發平臺。
iOS和Android都不支持JavaME應用程序,因此它現在已不再是主角。
JavaME包含Java類庫的一部分,同時提供了其他一些與移動設備交互的API。JavaME獲得
了重生,它現在名為JavaMEEmbedded,可用于商業IoT設備。
1.6其他JVM語言
為推廣Java語言和平臺,Sun很早就公布了JVM規范。這個文檔旨在供那些要自己動手編寫
JVV實現的開發人員參考,這些JVY實現可能是為那些沒有官方JVM實現的平臺編寫的。這個
文檔描述了JVM可執行的低級命令、必須提供的數據結構、內存訪問規則、Java字節碼文件
格式.class等。
這個規范的發布讓其他語言的設計者能夠嘗試Java字節碼,因此不久后其他語言也能夠編譯
成這種格式。這雖然不是Java設計者的初衷,但Sun(和后來的Oracle)樂見其成。它便是
如此地樂見其成,以至于僅僅為方便JVM支持動態語言而添加了新功能。
本芋將介紹與其他JV.M語言相關的如下主題。
?為何要放棄Java轉而使用其他語言進行JVM開發?
?在同一個項目中使用多種語言的可能性以及這樣做可能帶來的問題。
?使用不同于主項目使用的語言編寫單元測試。
1.6.1為何選擇其他語言
考慮到Java語言最初就是為在JVM上運行而設計的,怎么會有人選擇使用其他語言來進行JVM
開發呢?
開發人員這樣做的原因有多個:
是——種非常繁瑣的語言:
?J并a非va所有人都喜歡靜:態建嘉言,且靜態語言并非在任何情況下都是最佳選擇;
?Java類庫缺少一些經常需要用到的類。
?Java是一種非常繁瑣的語言
Java以繁瑣著稱。經過多年的修訂后,Java已不再那么繁瑣,但使用很多其他的語言時,完
成同樣的任務所需的代碼更少。
我們來看一個簡單的示例。
在Java中,標準的可修改對象通常類似于下面這樣:
classPerson{
privateStringname:
publicPerson(Stringname){
this,name=name;
}
publicStringgctNamcO\
returnname;
}
publicvoidsetName(Stringname){
this,name=name;
}
}
而使用Kotlin時,只需下面一行代碼就能實現同樣的功能(以及其他功能):
dataclassPerson(valname:String)
這可不是開玩笑。編譯這行代碼時,Kotlin將自動實現Java示例中定義的方法;實際上,它
還會添加其他較為常用的方法。第4章將討論這些額外的方法。
雖然使用其他語言可極大地提高效率,但Java也沒有看起來那么糟糕。所有現代IDE
編程工具都能自動生成Java樣板代碼,如前述示例中的樣板代碼。為此,你只需按下一個簡
單的組合鍵即可。
?Java并非對所有的人或在任何情況下都是理想選擇
雖然Java8新增了一些重要的函數式編程功能,但從本質上說,它依然是一種靜態的命令式
語言。并非所有的開發人員都喜歡這種編程風格。如果必須使用靜態語言來編寫代碼,Python
或Ruby程序員可能會哭暈在廁所。有鑒于此,有些團隊放棄Java轉而選擇使用其他語言來進
行JVM開發。
另外,對于有些問題,使用動態編程語言解決起來要優雅得多;同時對于必須執行復雜并發操
作的項目來說,函數式編程風格通常更合適。最后,對于有些哭和框架,通過某些語言來使用
讓人感覺更為自然。
?Java類庫缺失的類
Java類庫是一個龐大的庫,但它畢竟是20多年前推出的,因此在有些情況下缺少必要的類。
在大多數情況下,功能缺失的問題可通過添加JVV生態系統中免費的開源插件庫來解決,但如
果選擇使用內置了這些功能的語言,不僅更方便,還可節省時間。
例如,對于極其常用的JSON標準,JavaSE8的Java類庫就沒有提供原生支持。流行的插件
庫Jackson和GoogleGS0N提供了JS0N支持;另外,較新的JavaEE平臺版本也提供了支持
JSON的APE本書介紹的一些語言提供了原生的JSON支持。
另一個問題是,要使用Java類庫中的一-些常用類,必須編寫大量的樣板代碼。對于Java類庫
中的眾多常用類,諸如Groovy等語言都提供了包裝器,讓這些API使用起來輕松得多。
1.6.2在同一個項目中使用多種JVM語言
很多語言都能夠與Java互操作,因此也能夠與其他JVM語言互操作。這是通過盡可能為數據
結構使用標準Java類庫并像Java那樣編譯方法來實現的。
在Java項目中,經常使用其他語言來編寫某些類,但這樣做可能帶來一些問題:
?構建過程將復雜得多;
?很多語言要求使用自己的運行時類,這可能帶來問題。
?構建過程更復雜
使用多種語言時,必須調整構建腳本,這可能導致情況非常復雜。例如,如果Java項目使用
了用Groovy編譯的類,編譯順序將非常重要,即必須先編譯Groovy類,再編譯Java代四。
如果Groovy代碼使用了Java項目中的自定義類,情況將更加復雜。
你將在第11章看到,Groovy比較特殊。Groovy編譯器能夠編譯大部分Java代碼,因
為從很大程度上說,Groovy語言與Java語言兼容。在沒法這樣做或這樣做不可取時,有一個
用于構建工具ApacheYaven的編譯器插件,使用它可解決構建過程中面臨的問題。
一種解決之道是將代碼分成多個子項目,并在構建工具中將生成的庫作為主項目的需求列出。
有些語言提供了另一種解決方案:它們提供了自定義類,讓你能夠在Java(或其他JVM語言)
中調用這些語言的源代碼。被這些類加載時,源代碼將動態地編譯為Java字節碼。其他語言
實現了在Java代碼中嵌入腳本語言的官方標準;附錄A討論Oracle的JavaScript解釋器
Nashorn時,將簡要地討論這一點。
?語言運行時庫
從某種程度上說,這與構建并發癥相關。很多JVM語言都要求在編譯后的程序中包含支持率,
這些庫通常定義了語言特有的數據結構以及編譯得到的Java字節碼調用的內部支持方法。
這通常不是問題,但如果項目的依賴項(或依賴項的依賴項)是使用不同的語言版本編寫的,
就可能出現問題。如果同一個項目的多個庫要求使用同一個運行時庫的不同版本,情況將更為
復雜:編譯或運行項目時,可能出現令人費解的錯誤消息、。
這被稱為依賴惡夢(dependencyhell),但這并非是在同一個項Fl中使用多種語言特有的現
象,而是每個開發人員都應知道的現象。打算在同一個項目中變用多種語言的開發人員還必須
明白,語言運行時庫可能導致最終程序的規模急劇增大:有叱運行時庫還包含其依賴項.這將
增大出現依賴惡夢的風險。通常,語言的文檔或官網都詳細說明了其依賴項。
與很多框架設計者一樣,很多語言設計者都對這些問題心中有數,并采取了措施降低
這些問題出現的風險。例如,對于自己使用的較流行的依賴項,他們進行了重命名,以防發生
類名沖突。
1.6.3使用另一種語言編寫單元測試
使用其他語言編寫的單元測試來對Java代碼進行測試很常見c正如你在本章前面看到的,相
比于Java,使用其他語言編寫的代碼可能緊湊得多,這些語言非常適合用來編寫小型、具體
而易于理解的單元測試。
鑒于僅在運行單元測試時才會用到這些語言的運行時庫,因此無需在編譯得到的主項目中包含
它們。
你將在第11章看到,在這樣的情形下,非常適合使用Groovy。Groovy提供了一些便
利的單元測試編寫功能,其中包括內置的assert語句,這種語句在傳入的值與期望值不同時
將打印非常詳盡而易于理解的輸出。。
1.7小結
本章非常簡略地描述了JVMo首先介紹了JVV向開發人員提供的功能、JVM的常見用途以及最
重要的JVM概念;接下來探索了Java版本;最后介紹了其他JVM語言,以及開發人員放棄Java
轉而使用其他語言進行JVM開發的原因。
在下一章,我們將安裝并詳細介紹JDK,還將詳細介紹Java類庫并安裝其他開發工具,為動
手開發做好準備。
第2章Java虛擬機開發
本章深入介紹Java虛擬機(JVM),重點是每個JVM開發人員都必須知道的概念,而不管他選
擇使用的是哪種編程語言。本章涵蓋如下主題:
?Java開發包(JDK);
?使用包來組織類;
?Java類庫;
?從命令行運行JVM應用程序;
?安裝Eclipse集成開發環境(EclipseIDE)。
本書涵蓋Windows、macOS和Linux(Ubuntu)操作系統,但展示路徑時通常使用Windows風
格。如果你使用的是macOS或Linux,務必按相應操作系統的規則修改路徑。
2.1JDK
要進行JVM開發,必須安裝JDKJDK包含Java運行時環境(JavaRuntimeEnvironment,JRE)^
Java編譯器以及各種開發工具(本章將介紹其中的一些)。艮J便你的大部分開發工作都將使
用其他語言而不是Java來完成,也強烈建議你安裝完整的JDK,因為很多重要的開發工具都
必須安裝完整的JDK才能運行。另外,你遲早都將用到一些只有JDK才有的工具。
安裝較新的用于RaspberryPi的Linux發行版時,如果使用默認的Raspian安裝選項,將自
動安裝JavaSEEmbedded8JDK,但提供的版本通常不是最新的。其他主要的操作系統默認
安裝的JDK如何不得而知。木節介紹如下與JDK相關的主題:
?安裝JDK(WindowsniacOS和Linux);
?探索JDK;
?JREo
2.1.1安裝JDK
這里只介紹如何安裝Oracle的JDK8實現。如果你已安裝與JavaSE8平臺完全兼容的J3K
實現,包括開源的OpenJDK8或IBM的J9JDK8,通常也完全可行,因此你可以跳過本節。
非Oracle的JDK實現并不一定包含本書討論的所有功能,必要時我們將指出例外情況。
無論你使用的是哪種操作系統,都必須創建一個名為JAVAJIOME的環境變量,并讓它指向」DK
安裝目錄(在非開發計算機中為JRE所在的目錄)。對于本鬲涵蓋的操作系統(Windows.macOS
和Linux),我們將說明如何創建這樣的環境變量。很多重要的JVM工具都要用到這個變量,
包括構建工具和應用程序服務器。本節將介紹如何完成如下工作:
?下載JDK;
?在Windows系統中安裝JDK;
?在macOS系統中安裝JDK;
?在Linux系統中安裝JDK;
?下載JavadocAPI文檔。
?下載JDK
Oracle提供的用于Windows、macOS和Linux的JDK實現可從Oracle網站下載。對于有些平
臺,只有64位的JDK,而對于其他平臺,有32位和64位的。
使用你喜歡的瀏覽器訪問Oracle的Java主頁(http:〃www.oracle,com/java),如下圖所示。
?卜④廣“MV.-htm'
:*Rnr?l>n>-liwrrcSewch
ProductsSoMticnsStoreSupperTrainingPartre-iAt>2<rtQIN
JavaSonware
JavaYourNext(Cloud)
Javzi?th*eofkfsfxojr<t-nming
JBftr.」蒲同forCcroirrer?
OverviewRa”Techncioglei
要下載JDK,需執行如下步驟。
(1)本書編寫期間,該網頁包含一個JavaforDevelopers,單擊該按鈕將進入Software
Downloads部分。
(2)在列表中找到并單擊JavaSE(包含JavaFX)。如果它旁邊有鏈接EarlyAccess,請注
意不要單擊該鏈接。
(3)進入JavaSEDownloads頁面。單擊JDKF方的Download按鈕。
(4)根據你使用的操作系統平臺和體系結構,找到并單由相應的版本。
(5)如果你同意了許可條款,將下載相應版本的JDK。
?在Windows系統中安裝JDK
對于Windows操作系統,JDK有32位和64位的版本。你只需總行下載的可執行文件并按說明
做即可。請將JDK安裝路徑記錄下來,因為后面要用到。
請使用默認設置,這將隨JDK安裝JRE。強烈建議確保JRE和JDK的版本同步,因此使用JDK
安裝程序安裝JRE是最佳選擇。Oracle指出JDK始終是在系統級安裝的,因此其他所有用戶
都可使用它。
安裝完畢后,需要添加或修改一些環境變量。這里介紹如何在Windows10中這樣做,如果你
使用的是其他較新的Windows版本,做法應與之類似。
(1)右擊Windows“開始”按鈕并選擇“系統”,在出現的窗口中,單擊左邊的“高級系統設
置”。
(2)這將打開“系統屬性”對話框。單擊“環境變量”按鈕,這將打開如下圖所示的“環境變
量”對話框:
EnvironmentVariablesX
>crvariablesforVincent
VariableValje
DOCKER.TOOLBOX.INSTAL..C:\PfOgFilesyDockei"oolbox
PATHC:\Progr2mFil?\Mcrcurial^zXUsrrs^Vinccnt'iAppDataVLocarKatomV.
TEMP%USERPFOFILE%\AppData'?Locar\Tenp
TMP%LlSERFFOFILE%\AppDd^Locar\Tenip
MF-A.E(fiJDelete
Systemvarable:
VsnabeValueA
|JAVA_HOMFC:\lava\JDIGidk.1息0.112R
NUMBER.OF.PROCESSORS8
OSWindowsNT
PathC:\Java'JDK\jdkJ,3.0J⑵二八Pythcn27\C:\Dev\GNU$malltak\:..
PATHEXT(0M;,R;.SAT;.CM6VBS;V3EJS;JSe.V$F;M5H;JVISC
PROCESSCR_ARCHTECTUREAMD&4
PROCESSORIDENTiFERIntelaramtfv6Medel5CSteooina3Genuinelntd
N3“?Ecfit...Ddete
OK|Cantel
(3)在這個對話框底部的“系統變量”部分查找變量JAVA_H0;IE。如果沒有找到,就單擊按鈕
“新建”,否則對既有的JAVAJ40ME進行編輯。
(4)將變量名設置為JAVAJOME,并將值設置為JDK安裝目錄的完整路徑,再單擊“確定”按
鈕關閉打開的對話框。
(5)找到既有的變量Path,并在其中添加JDK安裝目錄下的子目錄bin的完整路徑;別忘了
用字符;將不同的目錄分隔。
為驗證安裝,可執行如下步驟。
(1)打開一個命令提示符窗口(為此,可單擊“開始”按鈕,輸入emd并按回車鍵)。
(2)輸入javac-version并按回車鍵。
你將看到一個版本號,它與下載的JDK版本相同。如果不是這樣,請核實你是否正確地修改了
環境變量,并確保你新打開了一個命令提示符窗口,而不是使用以前打開的命令提示符窗口。
?在
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 自我體型診斷
- 物流管理專業介紹
- 個人住房抵押貸款合同范本
- 供應鏈服務協議及勞務合同合同手冊
- 學生會工作總結和計劃
- 植物模擬練習題+答案
- 度校企合作人才培養合同
- 老人美容技巧培訓課件
- 供應鏈上下游合同大全
- 航空運輸公司短期職工合同
- 第5章 三角函數【知識導圖 】 高考數學復習思維導圖(人教A版2019)(必修第一冊)
- 《企業管理概論》試題庫及答案(完整版)
- 免疫機理圖與部分雞豬舍建筑圖課件
- chap3非理想流動反應器
- DBJ53T-19-2007加芯攪拌樁技術規程
- 2023年江蘇省生物學聯賽初賽預賽試題及答案(word版可編輯)
- (中職)飯店信息技術第六單元 客史檔案的管理教學課件
- 職稱評定打分細則(學院排名用)
- 語文新課標實踐與探索:《石壕吏》《茅屋為秋風所破歌》整合教學設計
- 液壓常用元件符號
- 消防設施維護保養記錄
評論
0/150
提交評論