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

CodeModel 實戰:用 Java 生成 Java 代碼的靈活範式

     編輯:Java 相關知識

為什麼需要代碼生成?

當大量代碼遵循固定模式(如 Entity → DAO/Service/Controller、DTO ↔ VO 轉換、Builder 模式)時,手工編寫不僅低效且易出錯。CodeModel 作為 JAXB 子項目,提供**程序化構建 Java 語法樹**的能力,輸出可編譯、可維護的 .java 文件,優於字符串拼接或模板引擎的類型安全與重構友好性。

核心 API 體系速覽

類職責
JCodeModel根容器,管理包/類/導入,最終 build(File) 落盤
JDefinedClass類/接口/枚舉定義,含字段/方法/構造器/註解創建
JMethod / JConstructor方法/構造器定義,body() 返回 JBlock
JBlock方法體,提供變量聲明、控制流、調用、賦值、返回等語句構建
JExpr表達式工廠:字面量、引用、新建、轉型、二元運算、方法調用鏈
JVar / JFieldVar局部變量 / 成員字段
JType / JClass類型引用,parseType("pkg.Type") 解析引用類型

關鍵編程模式示例

變量聲明與賦值

// 基本類型
JVar i = block.decl(cm.INT, "i", JExpr.lit(0));
// 引用類型
JType listType = cm.parseType("java.util.List<String>");
JVar list = block.decl(listType, "list", JExpr._new(cm.parseType("ArrayList")));
// 靜態常量
dc.field(JMod.PUBLIC | JMod.STATIC | JMod.FINAL, cm.INT, "MAX", JExpr.lit(100));

控制流構建

// if-else
JConditional iff = block._if(JExpr.ref("a").gt(JExpr.ref("b")));
iff._then().invoke("doA");
iff._else().invoke("doB");

// for 循環
JForLoop loop = block._for();
loop.init(cm.INT, "i", JExpr.lit(0));
loop.test(JExpr.ref("i").lt(JExpr.lit(10)));
loop.update(JExpr.ref("i").incr());
loop.body().invoke("process").arg(JExpr.ref("i"));

類/接口/繼承/實現

// 實體類
JDefinedClass clazz = cm._class("com.example.User");
// 抽象類
JDefinedClass abs = cm._class(JMod.PUBLIC | JMod.ABSTRACT, "com.example.Base", ClassType.CLASS);
// 接口
JDefinedClass iface = cm._class(JMod.PUBLIC, "com.example.Service", ClassType.INTERFACE);
// 繼承與實現
sub._extends(abs);
impl._implements(iface);

Javadoc 與註解

clazz.javadoc().add("用戶實體類").addParam("id", "主鍵");
method.annotate(Override.class);

完整案例:單例模式生成器

輸入:包名、類名。輸出:Singleton.java(雙重檢查鎖/靜態內部類任選)+ SingletonTest.java。

public class SingletonGen {
    public void gen() throws Exception {
        JCodeModel cm = new JCodeModel();
        JDefinedClass dc = cm._class("demo.Singleton");
        JType t = cm.parseType("demo.Singleton");
        // 私有構造器
        dc.constructor(JMod.PRIVATE);
        // 靜態實例字段
        dc.field(JMod.PRIVATE | JMod.STATIC | JMod.VOLATILE, t, "INSTANCE");
        // getInstance() 方法
        JMethod get = dc.method(JMod.PUBLIC | JMod.STATIC, t, "getInstance");
        JBlock body = get.body();
        JConditional c = body._if(JExpr.ref("INSTANCE").eq(JExpr._null()));
        JBlock sync = c._then()._synchronized(JExpr.ref("INSTANCE"));
        JConditional c2 = sync._if(JExpr.ref("INSTANCE").eq(JExpr._null()));
        c2._then().assign(JExpr.ref("INSTANCE"), JExpr._new(t));
        body._return(JExpr.ref("INSTANCE"));
        cm.build(new File("src"));
    }
}

生成代碼符合標準雙重檢查鎖單例,可直接編譯運行。

最佳實踐與避坑指南

  1. 類型安全優先:盡量用 cm.parseType() 而非字符串拼接類型
  2. 導入管理:CodeModel 自動處理 import,無需手工維護
  3. 格式化輸出:生成文件默認無縮進,可接入 Google Java Format 或 Eclipse Formatter 後處理
  4. 增量生成:對比現有文件僅在變更時覆寫,避免版本控制噪音
  5. 元數據驅動:結合 Annotation Processor 或配置文件(YAML/JSON)描述模板參數,實現「配置即代碼」
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved