码出高效
碼出高效
- 一.計算機基礎
- 1.1 0和1的世界
- 原碼,反碼,補碼
- 為什么出現反碼,補碼
- 位運算
- 1.2 浮點數
- 1.3 字符集與亂碼
- 1.4 CPU與內存
- 1.5 TCP/IP
- 1.6 信息安全
- 二.面向對象
- 2.1 OOP理念
- 2.2 初識Java
- 2.3 類
- 2.4 方法
- 三.代碼風格
- 3.1 命名規約
- 3.1.1 常量
- 3.1.2 變量
- 3.2 代碼展示風格
- 3.2.1 縮進,空格與空行
- 3.2.2 換行與高度
- 3.2.3 控制語句
- 四 走進JVM
- 4.1 字節碼
- 4.2 類加載過程
- 4.3 內存布局
- 4.4 對象實例化
- 4.5 垃圾回收
- 異常與日志
- 5.1 異常分類
- 5.2 try 代碼塊
- 5.3 異常的接與拋
- 5.4 日志
- 5.4.1 日志規范
- 5.4.2 日志框架
一.計算機基礎
1.1 0和1的世界
原碼,反碼,補碼
原碼就是符號位加上真值的絕對值, 即用第一位表示符號, 其余位表示值.
反碼的表示方法是:
正數的反碼是其本身
負數的反碼是在其原碼的基礎上, 符號位不變,其余各個位取反.
補碼的表示方法是:
正數的補碼就是其本身
負數的補碼是在其原碼的基礎上, 符號位不變, 其余各位取反, 最后+1. (即在反碼的基礎上+1)
為什么出現反碼,補碼
將符號位參與運算, 并且只保留加法的方法. 首先來看原碼:
計算十進制的表達式: 1-1=0
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2
為了解決原碼做減法的問題, 出現了反碼:
計算十進制的表達式: 1-1=0
1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0
發現用反碼計算減法, 結果的真值部分是正確的. 而唯一的問題其實就出現在"0"這個特殊的數值上. 雖然人們理解上+0和-0是一樣的, 但是0帶符號是沒有任何意義的. 而且會有[0000 0000]原和[1000 0000]原兩個編碼表示0.
補碼的出現, 解決了0的符號以及兩個編碼的問題:
1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]補 + [1111 1111]補 = [0000 0000]補=[0000 0000]原
位運算
<<左移 >>右移 >>>無符號右移
在左移<<與右移>>兩種運算中,符號位均參與移動,除負數往右移動,高位補l 之外,其他情況均在空位處補0
左移運算由于符號位參與向左移動,在移動后的結果中,最左位可能是1 或者0,
即正數向左移動的結果可能是正,也可能是負,負數向左移動的結果同樣可能是正,
也可能是負
對于三個大于號的>>〉無符號向右移動(注意不存在<<<無符號向左移動的運
算方式),當向右移動時,正負數高位均補0 ,正數不斷向右移動的最小值是0 ,而
負數不斷向右移動的最小值是l
為何負數不斷地無符號向右移動的最小值是l 呢?在實際編程中,位移運算僅作
用于整型(32 位)和長整型(64 位)數上,假如在整型數上移動的位數是32 位,無
論是否帶符號位以及移動方向,均為本身。因為移動的位數是個mod 32 的結果,
即35 >> 1 與3 5 ?33 是一樣的結果
1.2 浮點數
從數字時間的科學計數法映射到計算機世界的浮點數是,數值從十進制改為二進制,還要考慮內存硬件設備的實現方式.在規格化表示上存在差異,稱謂有所改變,指數稱為"階碼",有效數字稱為"尾數",所以用戶存儲符號,階碼,尾數的二進制位分別稱為符號位,階碼位,尾數位.
在最高二進制位上分配l 位表示浮點數的符號,0 表示正數,1 表示負數。
在符號位右側分配8 位用來存儲指數,
最右側分配連續的23 位用來存儲有效數字,
加減運算
在數學中,進行兩個小數的加減運算時,首先要將小數點對齊,然后同位數進行
加減運算。對兩個采用科學計數法表示的數做加減法運算時,為了讓小數點對齊就需
要確保指數一樣。當小數點對齊后,再將有效數字按照正常的數進行加減運算。
在要求絕對精確表示的業務場景下,比如金融行業的貨幣表示,推薦使用整型存
儲其最小單位的值,展示時可以轉換成該貨幣的常用單位,比如人民幣使用分存儲,
美元使用美分存儲。在要求精確表示小數點n 位的業務場景下,比如圓周率要求存儲
小數點后1000 位數字,使用單精度和雙精度浮點數類型保存是難以做到的,這時推
薦采用數組保存小數部分的數據。在比較浮點數時,由于存在誤差,往往會出現意料
之外的結果,所以禁止通過判斷兩個浮點數是否相等來控制某些業務流程。在數據庫
中保存小數時,推薦使用decimal 類型,禁止使用float 類型和double 類型。因為這
兩種類型在存儲的時候,存在精度損失的問題。
1.3 字符集與亂碼
在ASCII 碼中,有兩個特殊的控制字符10 和13 ,前者是LF 即“\n ”,后者是
CR 即V”,在編碼過程中,代碼的換行雖然是默認不可見的,但在不同的操{乍系統中’
表示方式是不樣的。在UNIX 系統中,換行使用換行符“\n,在window系統中,
換行使用"\r\n;在舊版macOS中,換行符使用回車符"/r",在新版macOS中使用
與UNIX 系統豐目同的換行方式。前編碼環境使用換行方式是LF ,
這也是推薦的換行方式,避免出現源碼在不同操作系統中換行顯示不同的情況。
1.4 CPU與內存
CPU ( Central Processing Unit )是一塊超大規模的集成電路板,是計算機的核心
部件,承載著計算機的主要運算和控制功能,是計算機指令的最終解釋模塊和執行模
塊。硬件包括基板、核心、針腳,基板用來固定核心和針腳,針腳通過基板上的基座
連接電路信號,CPU 核心的工藝極度精密,達到10 納米級別。CPU 的內部結
構如圖 所示。
內存物理結構由內存芯片、電路板、控制芯片、相關支持模塊等組成,內
存芯片結構比較簡單,核心是存儲單元,支持模塊是地址譯碼器和讀寫控制器,如圖所示。
1.5 TCP/IP
TCP/IP ( Transmission Control Protocol I Internet Protocol )中文譯為傳輸控制協
議/因特網互聯協議,這個大家族里的其他知名協議還有HTTP, HTT陀、FTP、
SMTP、UDP, ARP、PPP、IEEE 802.x 等。TCP/IP 是當前流行的網絡傳輸協議框架,
從嚴格意義上講它是一個協議族,因為TCP, IP 是其中最為核心的協議,所以就把
該協議族稱為TCP/IP
IP協議
IP是面向無連接、無狀態的,沒有額外的機制保證發送的包是否有序到達。IP
首先規定出IP 地址格式,該地址相當于在邏輯意義上進行了網段的劃分,給每臺計
算機額外設置了一個唯一的詳細地址。既然鏈路層可以通過唯一的MAC 地址找到機
器,為什么還需要通過唯的IP 地址再來標識呢?簡單地說,在世界范圍內,不可
能通過廣播的方式,從數以千萬計的計算機里找到目標MAC 地址的計算機而不超時。
連接池
在客戶端與服務端之間可以事先創建若干連接并提
前放置在連接池中,需要時可以從連接池直接獲取,數據傳輸完成后,將連接歸還至
連接池中,從而減少頻繁創建和釋放連接所造成的開銷。例如,RPC 服務集群的注冊
中心與服務提供方、消費方之間,消息服務集群的緩存服務器和消費者服務器之間,
應用后臺服務器和數據庫之間,都會使用連接池來提升性能。
1.6 信息安全
黑客與與安全
現代黑客攻擊的特點是分布式、高流量、深度匿名
互聯網企業都要建立一
套完整的信息安全體系,遵循CIA 原則,即保密性(Confidentiality ) ,完整性(Integrity ),可用性(Availability )
- 保密性。對需要保護的數據(比如用戶的私人信息等)進行保密操作,無論
是存儲還是傳輸,都要保證用戶數據及相關資源的安全。比如,在存儲文件
時會進行加密,在數據傳輸中也會通過各種編碼方式對數據進行加密等。 - 完整性。訪問的數據需要是完整的,而不是缺失的或者被篡改的,不然用戶
訪問的數據就是不正確的。比如,在商場看中一個型號為NB 的手機,但售
貨員在包裝的時候被其他人換成了更便宜的型號為LB 的于機,這就是我們
所說的資源被替換了,也就是不滿足完整性的地方。在實際編寫代碼中,一
定要保證數據的完整性,通常的做法是對數據進行簽名和校驗(比如MDS
和數字簽名等)。 - 可用性。服務需要是可用的。如果連服務都不可用,也就沒有安全這-說了。
比如還是去商場買東西,如果有人惡意破壞商場,故意雇用大量水軍在商場
的收銀臺排隊,既不結賬也不走,導致其他人無法付款,這就是服務已經不
可用的表現。這個例子和常見的服務拒絕(Dos )攻擊十分相似。對于這種情況,
通常使用訪問控制、限流等手段解決。
SQL注入
( I )過濾異戶輸入參&中的阿彌字符,從而降低被SQL ,t入的風險。
( 2 )禁止通過字符南拼撞的SQL i吾旬,嚴恪使用參數綁定傳人的SQL 參數c
( 3 )合理使月數據庫擊可框豆、提供的防左入機制。
XSS
XSS 跨站腳本攻擊,即
Cross-Site Scripting ,為了不幸日前端開發中層疊樣式表(css )的名字沖突,簡稱為
XSSa XSS 是指黑客通過技術手段,向正常用戶請求的HTML 頁面中插入惡意腳本,
從而可以執行任意腳本。
在防范xss 上,主要通過對用戶輸入數據做過濾或者轉義。比如Java 開發人
員可以使用Jsoup 框架對用戶輸入字符串做xss 過濾,或者使用框架提供的工具
類對用戶輸入的字符串做HTML 轉義,例如Spring 框架提供的HtmlUtils 。前端在
瀏覽器展示數據時,也需要使用安全的API 展示數據,比如使用innerText 而不是
innerHTML 。所以需要前、后端開發人員一同配合才能有效防范xss 漏洞。
CSRF
跨站請求偽造(Cross-Site Request Forgery ),簡稱CSRF ,也被稱為One-click
Attack , !l.D 在用戶并不知惰的情況下,冒充用戶發起請求,在當前已經登錄的Web 應
用程序上執行惡意操作,如惡意發帖、修改密碼、發郵件等。
xss 是在正常用戶請求的HTML 頁面中執行了黑客提供的惡意代碼,
cs 盯是黑客直接盜用用戶瀏覽器中的登錄信息,冒充用戶去執行黑客指定的操作。
xss 問題出在用戶數據沒有過濾、轉義l cs 盯問題出在HTTP 接口沒有防范不受信
任的調用。
防范CSRF 漏洞主要通過以下方式,
( I ) CSRF Token 驗證,利用瀏覽器的同源限制,在HTTP 接口執行前驗證頁面
或者Cookie 中設置的Token ,只有驗證通過才繼續執行請求。
( 2 )人機交互,比如在調用上述網上銀行轉賬接口時校驗短信驗證碼。
HTTPS
( I )瀏覽器向服務器發送請求,請求中包括瀏覽器支持的協議,并附帶一個隨
機數。
( 2 )服務器收到請求后,選擇某種非對稱加密算法,把數字證書簽有公鑰、身
份信息發送給瀏覽器,同時也附帶一個隨機數。
( 3 )瀏覽器收到后、驗證證書的真實性,用服務器的公鋁發送握手信息給服務器。
( 4 )服務器解密后,使用主前的隨機數計算出,個對稱加密的密鑰,以此作為
加密信息并發送。
( 5 )后續所有的信息發送都是以對稱加密方式進行的。
二.面向對象
2.1 OOP理念
面向過程讓計算機有步驟地順次做件事情,是種過程化的敘事思維。但是在
大型軟件開發過程中,發現用面向過程語言開發,軟件維護、軟件復用存在著巨大的
困難,代碼開發變成了記流水賬,久而久之就成為“面條”代碼,模塊之間互相輯合,
流程互相穿插,往往牽發而動全身。面向對象提出一種計算機世界里解決復雜軟件
工程的方法論,拆解問題復雜度,從人類思維角度提出解決問題的步驟和方案。
2.2 初識Java
Java 語言擁有跨平臺、分布式、多線程、健壯性等主要特點,是當下比較主流的
高級編程語言。它的類庫相當豐富、功能強大、簡單易用,對開發者相當友好,不僅
吸收了C++的優點,還摒棄了其難以掌控的多繼承、指針等概念。Java 比較好地實
現了面向對象理論,允許開發工程師以優雅的思維方式處理復雜的編程場景。
2.3 類
類的定義
類的定義由訪問級別、類型、類名、是否抽象、是否靜態、泛型標識、繼承或實
現關鍵字、父類或接口名稱等組成。類的訪問級別有public 和無訪問控制符,類型分
為class 、interface 、en um 。
接口與抽象類
正如面向對象四大特性(抽象、封裝、繼承、多態)所述,定義類的過程就是抽
象和封裝的過程,而接口與抽象類則是對實體類進行更高層次的抽象,僅定義公共行
為和特征。接口與抽象類的共同點是都不能被實例化,但可以定義引用變量指向實例對象
內部類
在個.java 源文件中,只能定義一個類名與文件名完全致的公開類,使用
public class 關鍵字來修飾。但在面向對象語言中1 任何一個類都可以在內部定義另外
一個類,前者為外部類,后者為內部類。內部類本身就是類的一個屬性,與其他屬性
定義方式一致。
- 靜態內部類,如static class StaticinnerC!ass {} ;
- 成員內部類,如:private class InstancelnnerC!ass {} ;
- 局部內部類,定義在方法或者表達式內部,
- 匿名內部類,如:(new Thread(){} ).start()。
訪問權限控制
面向對象的核心思想之一就是封裝,只把有限的方法和成員公開給別人,這也是
迪米特法則的內在要求,使外部調用方對方法體內的實現細節知道得盡可能少
在定義類時,推薦訪問控制級別從嚴處理.
( I )如果不允許外部直接通過new 創建對象,構造方法必須是pnvale 。
( 2 )工具類不允許有p u b l ic 或default 構造方法。
( 3 )類非s t a t ic 成員變雪并且與子類共享,必須是protected 。
( 4 )類非stat i c 成員變量并且僅在本類使用,必須是private 。
( 5 )類stat i c 成員變量如果僅在東類使用,必須是private o
( 6 )若是stat i c 成員變量,必須考慮是否為final o
( 7 )類成員方法只供類內部調用,必須是private 。
( 8 )類成員方法只對繼承類公開,那么限制為protected
this與super
對象實例化時,至少有條從本類出發抵達0 均ect 的通路,而打通這條路的兩
個主要工兵就是thi s 和s uper
類關系
有關系的
情況下,包括如下5 種類型,
- [繼承]extends (is-a )。
- [實現]implements (can-do)。
- [組合]類是成員變量(contai ns - a )。
- {聚合}類是成員變量(has-a)。
- [依賴]import 類(use-a )
序列化
( I ) Java 原生序列化
Java 類通過實現Serializable 接口來實現該類對象的序列化,
這個接口非常特殊,沒有任何方法,只起標識作用。Java 序列化保留了對象類的元數
據(如類、成員變量、繼承類信息等),以及對象數據等,兼容性最好,但不支持跨
語言,而且性能一般
實現Seri alizable 接口的類建議設置seria!VersionUID 字段值,如果不設置,那么
每次運行時,編譯器會根據類的內部實現,包括類名、接口名、方法和屬性等來自
動生成seria!Version UID 。如果類的源代碼有修改,那么重新編譯后seria!VersionUID
的取值可能會發生變化。因此實現Serializable 接口的類一定要顯式地定義
seria!Version UID 屬性值。修改類時需要根據兼容性決定是否修改serialVersionUID 值
- 如果是兼容升級,請不要修改seria!VersionUID 字段,避免反序列化失敗。
- 如果是不兼容升級,需要修改serialVersionUID 值,避免反序列化混亂。
使用Java 原生序列化需注意,Java 反序歹lj化時不會調用類的無參構造方法,而
是調用native 方法將成員變量賦值為對應類型的初始值。基于性能及兼容性考慮,不
推薦使用Java 原生序列化
( 2 ) Hessian 序列化。
Hessian 序列化是一種支持動態類型、跨語言、基于對象
傳輸的網絡協議。Java 對象序列化的二進制流可以被其他語言(如C++、Python )反
序列化。Hessian 協議具有如下特性.
- 自描述序列化類型。不依賴外部描述文件或接口定義,用一個字節表示常用基礎類型,極大縮短二進制流。
- 語言無關,支持腳本語言。
- 協議簡單,比Java 原生序列化高效。
相比Hessian 1.0, Hessian 2.0 中增加了壓縮編碼,其序列化二進制流大小是Java
序列化的50% ,序列化耗時是Java 序列化的30 % ,反序列化耗時是Java 反序列化的
20%
Hessian 會把復雜對象所有屬性存儲在一個Map 申進行序列化。所以在父類、子
類存在同名成員變量的情況下,Hessian 序列化時,先序列化子類,然后序列化父類,
因此反序列化結果會導致子類同名成員變量被父類的值覆蓋。
3 ) JSON 序列化
JSON ( JavaScript Object Notation )是一種輕量級的數據交
換格式。JSON 序列化就是將數據對象轉換為JSON 字符串。在序列化過程中拋棄了
類型信息,所以反序列化時只有提供類型信息才能準確地反序列化。相比前兩種方式,
JSON 可讀性比較好,方便調試
2.4 方法
方法簽名
方法簽名包括方法名稱和參數列表,是NM 標識方法的唯一索引,不包括返回值,
更加不包括訪問權限控制符、異常類型等。
參數
方法簽名包括方法名稱和參數列表,是NM 標識方法的唯一索引,不包括返回值,
更加不包括訪問權限控制符、異常類型等。
無論是對于基本數據類型,還是引用變量,Java 中的參數傳遞都是值
復制的傳遞過程。對于引用變量,復制指向對象的首地址,雙方都可以通過自己的引
用變量修改指向對象的相關屬性。
構造方法
構造方法(Constructor )是方法名與類名相同的特殊方法,在新建對象時調用,
可以通過不同的構造方法實現不同方式的對象初始化,它有如下特征,
( I )構造1J 沽名稱必示與吳兵相同。
( 2 )均圭方江主二沒有返國類在二吶,即使是void tli,-懷能有z 它返回對象的地址,
并賦值給引用變量。
( 3 )枯l z 丁、-t: 吉~ t … ,’ .(…’ T 市被ff 弓. -.T ‘i「妒土I’" 調用途徑有三種
一是通過new 關鍵字,二是在子類的構造方法中通過super 調用父類的構造方法,三
是通過反射方式獲取并使用。
( 4 )吳王飛jj fo~ +「J 認-~ ._送去均王元、去但是如果顯式定義了有參構造方法,
則此無參構造方法就會被覆蓋,如果依然想擁有,就需要進行顯式定義。
( 5 )均生于1 、主以和平外部無法使用私有構造方法創建對象。
類內方法
除構造方法外,類中還可以有三類方法實例方法、
靜態方法、靜態代碼塊。
getter與setter
在實例方法中有類特殊的方法,即ge憂er 與se憂er 方法,它們一般不包含任何
業務邏輯,僅僅是為類成員屬性提供讀取和修改的方法,這樣設計有兩點好處I
(!)滿足面向對象語言封裝的特’生。盡可能將類中的屬性定義為private ,針對
屬性值的訪問與修改需要使用相應的getter 與se位er 方法,而不是直接對public 的屬
性進行讀取和修改。
( 2 )有利于統一控制。雖然直接對屬性進行讀取、修改的方式和使用相應的
getter 與se憂er 方法在效果上是一樣的,但是前者難以應對業務的變化。
同步與異步
同步調用是因剛性調用,是阻塞式操作,必須等待調用方法體執行結束。而異步調
用是柔性調用,是非阻塞式操作,在執行過程中,如調用其他方法,自己可以繼續執
行而不被阻塞等待方法調用完畢。
覆寫
多態中的overri de ,本書翻譯成覆寫。如果翻譯成重寫,那么與重構意思過于
接近;如果翻譯成覆蓋,那么少了“寫”這個核心動詞。
方法的覆寫可以總結成容易記憶的口訣“一大兩小兩同”。
- 一大子類的方法訪問權限控制符只能相同或變大。
- 兩小,拋出異常和返回值只能變小,能夠轉型成父類對象。子類的返回值、
拋出異常類型必須與父類的返回值、拋出異常類型存在繼承關系。 - 兩同i 方法名和參數必須完全相同。
重載
在同一個類中,如果多個方法有相同的名字、不同的參數,即稱為重載,比如一
個類中有多個構造方法。JVM在重載方法中,選擇合適的目標方法的順
序如下
泛型
泛型的本質是類型參數化,解決不確定具體對象類型的問題。在面向對象編程語
言中,允許程序員在強類型校驗下定義某些可變部分,以達到代碼復用的目的。
- 尖捂號里的每個元素都指代一種未知類型。
- 尖括號的位置非常講究,必須在類目之后或方法返回值之前
- 泛型在定義處只具備執行Object方法的能力
- 對于編譯之后的字節碼指令,其實沒有這些花頭花腦的方法簽名,充分說明泛型只是一種編寫代碼時的語法檢查
數據類型
I )對象頭(Object !leader )
對象頭占用12 個字節,存儲內容包括對象標記(markOop )和類元信息(klassOop )。
對象標記存儲對象本身運行時的數據,如哈希碼、GC 標記、鎖信息、線程關聯信息等,
這部分數據在64 位NM 上占用8 個字節,稱為"Mark word",為了存儲更多的狀
態言息,對象標記的存儲恪式是非固定的(具休與JVM 的實現有關)。類元信患、存
儲的是對象指向它的類元數據(即Kl ass )的首地址’占用4 個字節,與refvar 開銷一致。
( 2 )實例數據(Instance Data )
存儲本類對象的實例成員變量和所有可見的父類成員變量。如Integer 的實例
成員只有一個private int value ,占用4 個字節,所以加上對象頭為16 個字節1 再
如,上述示例代碼的R巳fObjDemo 對象大小為48 個字節,一個子類RefObjSon 繼承
RefObjDemo ,即使子類內部是空的,n ew RefObjSon 的對象也是占用48 個字節。
( 3 )對齊填充(Padding )
對象的存儲空間分配單位是8 個字節,如果一個占用大小為16 個字節的對象,
增加一個成員變量byte 類型,此時需要占用17 個字節,但是也會分配24 個字節進
行對齊填充操作。
包裝類型
( I ) 所有的POJO 類屬性必須使用包裝數據類型
( 2 ) RPC 方法的返回值和參數必須使用包裝數據類型。
( 3 )所有的局部變量推薦使用基本數據類型。
字符串
字符串相關類型主要有三種String 、Strin gBuild 町、Strin gBuffer 。String 是只讀
字符串,典型的immutabl e 對象,對它的任何改動,其實都是創建一個新對象,再把
引用指向該對象。Strin g 對象賦值操作后,會在常量池中進行緩存,如果下次申請創
建對象時,緩存中已經存在,貝lj直接返回相應引用給創建者。而StringBuffer 貝lj 可以
在原對象上進行修改,是線程安全的。JDK5 號|入的Str i ngBuilder 與StringBuffer 均繼
承自AbstractStringBui Ider ,兩個子類的很多方法都是通過飛uper . 方法。”的方式調
用抽象父類中的方法,此抽象類在內部與String 一樣,也是以字符數組的形式存儲字
符串的。StringBuilder 是非線程安全的,把是否需要進行多線程加鎖交給工程師決定,
操作效率比StringBuffer 高。線程安全的對象先產生是因為計算機的發展總是從單線
程到多線程,從單機到分布式。
三.代碼風格
3.1 命名規約
- 包名統使用小寫,點分隔符之間有且僅有個自然語義的英語單詞。包名
統一使用單數形式,但是類名如果有復數含義,則可以使用復數形式。 - 抽象類命名使用Abstract 或Base 開頭;異常類命名使用Exception 結尾,測
試類命名以它要測試的類名開始,以Test 結尾。 - 類型與中括號緊挨相連來定義數組。
- 枚舉類名帶上Enum 后綴,枚舉成員名稱需要全大寫,單詞間用下畫線隔開
3.1.1 常量
- 采用字母全部大寫、單詞之間加下畫線的方式。而局部常量采用小駝峰形式即可。
- 避免魔法值,幾乎是固定不變的全局常量采用枚舉,普通常量采用不能實例化的抽象類
3.1.2 變量
變量的命名需要滿足小駝峰格式,命名體現業務含義即可。存在一種特殊情況,在定義類成員變量時,特別是在POJO 類中,針對布爾類型的變量,命名不要加is 前綴,否則部分框架解析會引起序列化錯誤。
3.2 代碼展示風格
3.2.1 縮進,空格與空行
采用4 個空恪的縮進方式
( I )任何二目,三目運算符的左右兩邊都必須加一個空格.
( 2 )注釋的雙斜線與注釋內容之間有且僅有一個空恪。
( 3 )方法參數在定義和傳入時,多個參數逗號后面必須加空格。
( 4 )沒有必要增加若干空格使變量的賦值等號與上一行對應的位置的等號對齊
( 5 )如果大括號內為空,則可以簡寫成{}即可, 大括號中間無需換行和空格
( 6 )左右小括號與括號內部的相鄰字符之間不要出現空格.
( 7 ) 左大括號前需要加空格
空行用來分隔功能相似、邏輯內聚、意思相近的代碼片段,使得程序布局更加清
晰
3.2.2 換行與高度
約定單行字符數不超過120 個,超出則需要換行,換行時遵循如下原則:
( I )第二行相對第一行縮進4個空格,從第三行開始,不再繼續縮進,參考示例。
( 2 )運算符與下文一起換行。
( 3 )方法調用的點符號與下文一起換行。
( 4 )方法調用中的多個參數需要換行時,在逗號后換行。
( 5 )在括號前不要換行。
約定單個方法的總行數不超過80 行
3.2.3 控制語句
四 走進JVM
4.1 字節碼
Java 所有的指令有200 個左右,一個字節(8 位)可以存
儲256 種不同的指令信息,一個這樣的字節稱為字節碼(Bytecode )。在代碼的執行
過程中,NM 將字節碼解釋執行,屏蔽對底層操作系統的依賴l NM 也可以將字節
碼編譯執行,如果是熱點代碼,會通過刀T 動態地編譯為機器碼,提高執行效率
4.2 類加載過程
第一步,Load 階段讀取類文件產生二進制流,并轉化為特定的數據結構,初步
校驗cafe babe 魔法數、常量池、文件長度、是否有父類等,然后創建對應類的java.
Jang.Class 實例。
第二步,Link 階段包括驗證、準備、解析三個步驟。驗證是更詳細的校驗,比
如final 是否合規、類型是否正確、靜態變量是否合理等i 準備階段是為靜態變量分
配內存,并設定默認值,解析類和方法確保類與類之間的相互引用正確性,完成內存
結構布局。
第三步,Init 階段執行類構造器<clinit> 方法,如果賦值運算是通過其他類的靜
態方法來完成的,那么會馬上解析另外個類,在虛擬機槍中執行完畢后通過返回值
進行賦值。
4.3 內存布局
Heap 是OOM 故障最主要的發源地,它存儲著幾乎所有的實例對象,堆由垃圾
收集器自動回收,堆區由各子線程共享使用。通常情況下,它占用的空間是所有內存
區域中最大的,但如果無節制地創建大量對象,也窯易消耗完所有的空間。堆的內存
空間既可以固定大小,也可以在運行時動態地調整,通過如下參數設定初始值和最大
值,比如-Xms256M -Xmxl024M ,其中-X 表示它是JVM 運行參數,ms 是memory
start 的簡稱,mx 是memory max 的簡稱,分別代表最小堆窯量和最大堆窯量。
早在JDK8版本中,無空間的前身Perm 區已經被淘汰。在JDK7 及之前的版本中,只有Hotspot
才有Perm 區,譯為永久代,它在啟動時固定大小,很難進行調優,并且FGC 時會移
動類無信息。在某些場景下,如果動態加載類過多,容易產生Perm 區的OOM 。
區別于永久代,元空間在本地內存中分配。在JDK8 里,Perm 區中的所有內容
中字符串常量移至堆內存,其他內容包括類元信息、字段、靜態屬性、方法、常量等
都移動至無空間內,比如圖4-10 中的0均ect 類元信息、靜態屬性System.out 、整型
常量10000000 等。圖4-10 中顯示在常量池中的Strir 氈,其實際對象是被保存在堆內
存中的。
棧(Stack )是-個先進后出的數據結構,就像子彈的彈夾,最后壓入的子彈先發射,
壓在底部的子彈最后發射,撞針只能訪問位于頂部的那一顆子彈。
本地方法棧(Native Method Stack )在JVM 內存布局中,也是結程對象私有的,
但是虛擬機棧“主內”,而本地方法棧“主外”。
每個線程在創建后,都會產生自己的程序計數器和枝幀,程序計數器用來存放執行指令的偏移量和行號指示器等,線程執行或恢復都要依賴程序計數器。程序計數器在各個線程之間互不影響,此區域也不會發生內存溢出異常。
最后,從線程共享的角度來看,堆和元空間是所有線程共享的,而虛擬機枝、本
地方法枝、程序計數器是線程內部私有的,從這個角度看下Java 內存結構,如圖4-12
所示。
4.4 對象實例化
4.5 垃圾回收
Java 會對內存進行自動分配與回收管理,使上層業務更加安全,方便地使用內存
實現程序邏輯。在不同的口爪4 實現及不同的回收機制中,堆內存的劃分方式是不一
樣的,垃圾回收的主要目的是清除不再使用的對象,自動釋放內存。
異常與日志
5.1 異常分類
JDK 中定義了套完整的異常機制,所有異常都是Throwable 的子類,分
為Error (致命異常)和Exception (非致命異常)。Error 是一種非常特殊的異
常類型,它的出現標識著系統發生了不可控的錯誤,例如StackOverflowError 、
OutO島1 emoryEηor 。針對此類錯誤,程序無法處理,只能人工介入。Exception 又分
為ch ecked 異常(受檢異常)和unchecked 異常(非受檢異常)。
5.2 try 代碼塊
try-catch-finally 是處理程序異常的三部曲。當存在try 時,可以只有catch 代碼塊,
也可以只有finally 代碼塊,就是不能單獨只有try 這個光桿司令。
5.3 異常的接與拋
契約式編程理念就完全處于防御式編程理念的下風,
所以我們推薦方法的返回值可以為null ,不強制返回空集合或者空對象等,但是必須
添加注釋充分說明什么情況下會返回null 值。防止NP E 定是調用方的責任,需要
調用方進行事先判斷。
5.4 日志
記錄應用系統曰志主要有三個原因記錄操作軌跡、監控系統運行狀況、
回溯系統故障。
5.4.1 日志規范
應用中的擴展日志命名方式應該有統-
的約定,通過命名能直觀明了地表明當前日志文件是什么功能,如監控、訪問日志
等。推薦的日志文件命名方式為appName_logType logName.log 。其中,log Type 為
日志類型,推薦分類有stats 、monitor 、visit 等,logNam e 為日志描述。這種命名的
好處是通過文件名就可以知道曰志文件屬于什么應用,什么類型,什么目的,也有利
于歸類查找。例如,mppserv er 應用中單獨監控時區轉換異常的日志文件名定義為
mppserver monitor timeZoneConvert.log 。
代碼規約推薦曰志文件至少保存1 5 天,可以根據日志文件的重要程度、
文件大小及磁盤空間再自行延長保存時間。
5.4.2 日志框架
日志框架分為三大部分,包括日志門面、曰志適配器、日志庫。
門面設計模式是面向對象設計模式中的一種,日志框架采用的就是這種模式,類
似JDB C 的設計理念。它只提供一套接口規范,自身不負責日志功能的實現,目的是
讓使用者不需要關注底層具體是哪個日志庫來負責日志打印及具體的使用細節等。目
前用得最為廣泛的曰志門面有兩種slf4j 和commons -logging 。
它具體實現了日志的相關功能,主流的日志庫有三個,分別是log4j 、log -jdk 、
logback 。最早Java 要想記錄曰志只能通過System.out 或System.err 來完成,非常不方便。
log4j 就是為了解決這一問題而提出的,它是最早誕生的曰志庫。接著JD K 也在1 .4 版
本引入了一個日志庫java. util.logging. Logger.,簡稱log-dk。這樣市面上就出現兩種日志
功能的實現,開發者在使用時需要關注所使用的日志庫的具體細節。logback 是最晚出
現的,它與log4j 出自同一個作者,是log4j的升級版且本身就實現了slf4j的接口。
曰志適配器分兩種場景
( I )日志門面適配器,因為slf4j規范是后來提出的此之前的日志庫是沒有
實現slf4j的接口的,例如log4j ;所以在工程里要想使用slf4j +log4j 的模式,就額
外需要個適配器(slf4j-log4j12 來解決接口不兼容的問題。
( 2 )日志庫適配器,在一些老的工程里,一開始為了開發簡單而直接使用了日志庫API來完成曰志打印,隨著時間的推移想將原來直接調用日志庫的模式改為業界標準的門面模式(例如slf4j +logback 組合),但老工程代碼里打印曰志的地方太多,難以改動,所以需要個運隊器來完成從舊日志庫的API 到slf4j 的路由,這樣在不改動原有代碼的情況l、也能使用slf4j叫來統一管理曰志,而日后續自由替換具體日志庫也不成可題。
總結
- 上一篇: c#让电脑锁定、注销、关机
- 下一篇: 云南干旱 谁人受损 心有戚戚 愤怒哀