因專案需求將 C# 的 CYQ.Data V5 移植至 Java,發現兩語言雖語法相似,但執行細節差異極大,不得不重寫核心組件。本文記錄移植過程中遇到的 10 大語言差異,並完整展示自製 JSON 解析器的三大核心類與測試代碼。
| C# 特性 | Java 替代方案 |
|---|---|
ref 參數(引用傳遞,可改變呼叫端引用) | 無直接對應;改用包裝類、陣列或回傳新物件 |
out 參數(多重回傳) | 改回傳陣列、Collection 或自訂 Result 物件 |
SqlDbType / DbType | JDBC 使用 java.sql.Types 常數 |
DBNull.Value | 直接用 null;PreparedStatement 用 setNull() |
Convert.ChangeType 通用轉型 | 自寫工具類或用 Apache Commons BeanUtils |
反射判斷泛型 IsGenericType、Nullable.GetUnderlyingType | 用 Type / ParameterizedType 檢查;無 nullable 基礎型別概念 |
| Map 預設排序 | 僅 LinkedHashMap 保持插入順序 |
代碼摺疊 #region | 需安裝外掛,改用 //region 註解 |
internal 組件可見性 | Java 無對應;只能用 package-private 或 public |
| 其他大小寫、方法命名差異 | 逐一適配 |
追蹤 JSON 解析過程中的巢狀層級、鍵值階段、引號模式、轉義字元等狀態。
package cyq.data.tool;
class CharState {
boolean jsonStart = false;
boolean setDicValue = false;
boolean escapeChar = false;
boolean arrayStart = false;
boolean childrenStart = false;
int state = -1; // 0:取名稱中, 1:取值中
int keyStart = -1; // -1未初始化, 0未開始, 1無引號, 2單引號, 3雙引號
int valueStart = -1;
boolean isError = false;
void CheckIsError(char c) { /* 依字元檢查語法錯誤 */ }
}
IsJson(str):快速判斷字串是否合法 JSONSplit(json):將 JSON 物件拆解為 List<LinkedHashMap<String,String>>,保留欄位順序GetValueLength():遞迴計算巢狀值長度(處理物件/陣列嵌套)SetCharState():逐字元狀態機驅動,識別 { } [ ] : , " ' 等關鍵字元關鍵設計:
LinkedHashMap 保證欄位順序public class JsonHelper {
public static boolean IsJson(String json) { return JsonSplit.IsJson(json); }
public static Map<String,String> Split(String json) { /* 取第一個 Map */ }
public static List<LinkedHashMap<String,String>> SplitArray(String jsonArray) { /* 陣列轉多筆 Map */ }
}
測試涵蓋:標準 JSON、無引號鍵名、巢狀物件/陣列、null 值、轉義字元等場景。結果證明解析器能正確處理常見結構,並優雅降級處理非標準輸入。
「雖然 Java 很原始,C# 很高級,但技術走向極端後,也得學學大閘蟹,得橫著走。只有兩手抓、兩手都硬,才不會被技術所孤立。」
造輪子過程雖痛苦,卻能深入理解語言本質與資料結構。完整代碼已開源於專案 cyq.data.tool 套件,歡迎參考改進。