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

Java 核心基礎必懂 6 大陷阱:引用、equals、String、final、初始化、instanceof

     編輯:Java 相關知識

前言

這些問題看似基礎,卻是無數開發者 (含資深者) 的痛點。搞不清這些,就談不上精通 Java。內容整理自 CSDN 經典老貼,逐一拆解。

陷阱一:聲明了什麼?—— 變數 ≠ 物件

String s = "Hello world!";

錯誤認知: 「宣告了一個內容為 Hello world 的 String 物件」

正確認知: 宣告了一個參考變數 s,型別為 String,目前指向字串常量池中的 "Hello world!" 物件。

String s = "Hello";
String s2 = s;  // 未產生新物件!s2 指向同一個 "Hello"
s = s + " world"; // s 指向新物件 "Hello world",原 "Hello" 仍在常量池

結論: 參考變數存的是記憶體地址,非物件本身。new String("...") 強制建立新物件,"" 字面量共用常量池。

陷阱二:== vs equals()

運算子/方法比較內容範例結果
==參考變數的值 (記憶體地址)new String("foo") == new String("foo") → false
equals()物件邏輯內容 (由類別定義)new String("foo").equals(new String("foo")) → true
// Object.equals() 預設實作
public boolean equals(Object o) { return this == o; }

警示: 自訂類別若未覆寫 equals(),行為同 ==。使用 HashSet/HashMap 等基於雜湊的集合時,必須同時覆寫 equals() 與 hashCode(),且邏輯一致。

陷阱三:String 真的變了嗎?—— 不變性

String s = "Hello";
s = s + " world"; // s 變了嗎?

答案: 原物件 "Hello" 沒變,s 參考變數改指向新物件 "Hello world"。String 為 不可變 類別。

效能啟示: 大量字串拼接請用 StringBuilder (非執行緒安全、效能佳) 或 StringBuffer (執行緒安全)。

// 正確初始化:直接指向常量池
private String s = "Initial value";  // 多個實例共用同一物件

// 錯誤初始化:每次 new 產生新物件
private String s = new String("Initial value"); // 浪費記憶體與 CPU

陷阱四:final 修飾的是什麼?

final StringBuilder sb = new StringBuilder("immutable");
sb = new StringBuilder("oops"); // 編譯錯誤:無法改變參考指向

final StringBuilder sb2 = new StringBuilder("immutable");
sb2.append(" broken!"); // 編譯通過!物件內容可變

鐵律: final 僅鎖定參考變數的指向,不鎖定物件內部狀態。多執行緒共享 final 參考指向的可變物件,仍需同步機制 保護。

陷阱五:變數初始化規則

變數類型初始化時機預設值備註
類別屬性 (instance)建立實例時0/false/null/0.0...可指定初始值
類別屬性 (static)類別載入時 (首次使用前)同上僅初始化一次
區域變數 (方法內)必須手動初始化無 (編譯器強制檢查)使用前未初始化 → 編譯錯誤
方法參數呼叫時由呼叫端提供無本質為區域變數

區域變數初始化技巧: 宣告即賦值預設值 (int i = 0; String s = null;),避免分支導致未初始化。

陷阱六:instanceof 是什麼?

String s = "I am an Object!";
boolean isObject = s instanceof Object; // true

instanceof 為二元運算子 (保留字),測試左側物件是否為右側類別 (或子類別/實作介面) 的實例。

反模式: 用 instanceof + 強制轉型取代多型

// 差勁做法
if (bill instanceof PhoneBill) calcPhone((PhoneBill)bill);
else if (bill instanceof GasBill) calcGas((GasBill)bill);

// 正確做法:方法多載/覆寫
double calc(PhoneBill b) { ... }
double calc(GasBill b) { ... }

附錄:Java 程式碼風格規範精要

命名

  • Package:全小寫 com.company.module
  • Class:PascalCase OrderService
  • Field/Parameter:camelCase orderId
  • Constant:UPPER_SNAKE MAX_RETRY_COUNT
  • Array:byte[] buffer; (非 byte buffer[];)

檔案結構

  1. 版權宣告
  2. Package 宣告
  3. Import (標準庫優先、字母序、同包用 *)
  4. Class 文件註解
  5. Class 宣告 (extends/implements 換行)
  6. Fields (public 需 Javadoc)
  7. Accessors (簡單 getter/setter 可單行)
  8. Constructors (參數多者後置)
  9. clone()、toString()
  10. Business Methods
  11. main() (置底)

格式細節

  • 縮排:2 空格,禁用 Tab
  • 行寬:80 字元,超長在逗號/運算子後換行並多縮 2 格
  • 大括號:獨佔一行,右括號對齊左括號行
  • 括號緊貼:method(arg) 不要 method( arg )
  • 無意義括號禁止:if (i == 42) 非 if ((i) == 42)

程式設計原則

  • System.exit() 僅限 main() 呼叫
  • 拋出 RuntimeException 衍生類別,頂層 main() 捕獲並記錄所有異常
  • 資源用畢即釋放 (try-with-resources),不仰賴 GC
  • 慎用 final 類別 (除非架構要求)
  • 欄位預設 protected 利於繼承
  • 效能:避免迴圈中 new 物件、字串拼接用 StringBuilder、減少 synchronized 範圍
  • 跨平台:換行用 System.lineSeparator() 或 println()
  • PrintStream 已棄用,改用 PrintWriter

內化這 6 大陷阱與風格規範,是從「會寫 Java」邁向「寫好 Java」的關鍵門檻。

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