首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

《高質量 Java 代碼 151 條建議》第 2 章精讀:基本型別陷阱與最佳實踐(建議 21-25)

     編輯:Java 綜合教學

前言

「不積跬步,無以至千里;不積小流,無以成江海。」—— 荀子《勸學篇》。本文深入解析《編寫高質量代碼:改善 Java 程序的 151 個建議》第 2 章基本型別部分的建議 21 至 25,透過實戰代碼與反面教材,幫助開發者避開基本型別使用中的隱蔽坑洞。

建議 21:判斷奇偶請用「偶判斷」,勿用「奇判斷」

錯誤示範

String result = (i % 2 == 1) ? "奇數" : "偶數";

問題根因

Java 的取餘運算 % 定義為 dividend - dividend / divisor * divisor。負數取餘時,結果帶負號:-1 % 2 == -1,導致 -1 被誤判為偶數。

正確寫法

String result = (i % 2 == 0) ? "偶數" : "奇數";

核心原則: 知其然,更要知其所以然。基本知識的底層實作細節決定正確性。

建議 22:貨幣計算請用整數型別或 BigDecimal

浮點數陷阱

System.out.println(10.00 - 9.60); // 輸出 0.40000000000000036

0.4 在二進制中為無限循環小數,無法精確表示。格式化輸出雖能掩蓋,但大量累加會產生不可接受的誤差。

兩種解決方案

  1. BigDecimal:專為精確計算設計,支援加減乘除與縮放,資料庫 DECIMAL 欄位映射首選。
  2. 整數擴大法:金額乘 100 轉為分(長整型),運算後再除 100 顯示。零售、POS 系統常用,效能優於 BigDecimal。

建議 23:勿讓型別隱式轉換「偷偷」發生

經典溢位案例

public static final int LIGHT_SPEED = 30 * 10000 * 1000; // 300,000,000
long dis2 = LIGHT_SPEED * 60 * 8; // 本意計算 8 光分鐘距離

右側三個 int 先相乘,結果溢位變負數,再隱式轉為 long,終得錯誤結果 -2028888064。

修正姿勢

long dis2 = 1L * LIGHT_SPEED * 60 * 8; // 首因子加 L,強制全鏈路長整型運算

最佳實踐: 主動宣告型別(1L、1.0、1f),讓編譯器在最早階段完成擴型,杜絕隱式轉換驚喜。

建議 24:邊界測試不可或缺,防禦性程式設計要貫徹始終

整數溢位繞過業務檢核

if (order > 0 && order + cur <= LIMIT) { // LIMIT = 2000, cur = 1000
    // 通過檢核
}

攻擊者輸入 Integer.MAX_VALUE (2147483647),order + cur 溢位變負數,條件成立,繞過限額。

防護清單

  • 單元測試必測:0、正最大值、負最小值
  • 前端 JS 檢核只能擋「誠實用戶」,後端必須二次驗證
  • 使用 Math.addExact() (Java 8+) 或手動檢核 order > LIMIT - cur 避免溢位

建議 25:四捨五入有統計偏差,金融場景請用「銀行家捨入法」

傳統四捨五入的隱性虧損

Math.round(10.5) = 11,Math.round(-10.5) = -10。正負非對稱,長期大量計息會造成銀行持續虧損(每千萬戶每年約損失 10 萬元)。

銀行家捨入法規則

四捨六入五考慮,五後非零進一,五後為零看奇偶:五前為偶捨去,五前為奇進一。

Java 實作

BigDecimal interest = principal.multiply(rate)
    .setScale(2, RoundingMode.HALF_EVEN); // HALF_EVEN 即銀行家捨入

RoundingMode 七種模式對照表:

模式行為典型場景
UP遠離零方向稅務計算
DOWN趨近零方向(截斷)折扣計算
CEILING趨近正無窮債務人有利
FLOOR趨近負無窮債權人有利
HALF_UP傳統四捨五入一般商業
HALF_DOWN五捨六入特定會計準則
HALF_EVEN銀行家捨入(統計誤差最小)金融、科學計算首選
UNNECESSARY要求精確,否則拋出異常嚴格精確場景

總結

基本型別看似簡單,實則暗藏 Java 語言設計、JVM 實作、IEEE 754 浮點數標準等深層知識。養成「主動宣告型別、邊界優先測試、金融用 BigDecimal + HALF_EVEN」的肌肉記憶,是寫出健壯代碼的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved