Android 編譯時代碼生成技術探究 二 JavaPoet生成 .java源文件的Java API

https://github.com/979451341/TestAPT

這篇說如何生成Java文件,所使用的就是JavaPoet這個API提供的代碼氯哮,讓我們來學習如何去使用它色难。

1.添加定死的代碼

比如我想要生成如下代碼的java文件

package com.example;

public final class TestClass {

void main() {

int total = 0;

for (int i = 0; i < 10; i++) {

total += i;

}

}

}

那生成代碼如下

MethodSpec main = MethodSpec.methodBuilder("main")

.addCode(""

+ "int total = 0;\n"

+ "for (int i = 0; i < 10; i++) {\n"

+ "? total += i;\n"

+ "}\n")

.build();

TypeSpec testClass = TypeSpec.classBuilder("TestClass")

.addModifiers(Modifier.PUBLIC,Modifier.FINAL)

.addMethod(main)

.build();

JavaFile javaFile = JavaFile.builder("com.example",testClass)

.build();

通過以上代碼可以看出,JavaPoet很多時候都是用的Builder模式來構建代碼永品,這個MethodSpec是用來新建函數(shù)的圃酵,通過methodBuilder取函數(shù)名并通過addCode來添加代碼,TypeSpec則是用來生成類嘿歌,通過classBuilder來創(chuàng)建和去類名掸掏,通過addModifiers來規(guī)定類的屬性,然后通過addMethod添加函數(shù)搅幅。最后是通過JavaFile來生成相應包下的java文件阅束,指定了包名和類呼胚。

后面我會重點說MethodSpec如何用茄唐,就不貼完整代碼了

2.引用自己給參數(shù)

以上代碼還有另一種方法生成,addStatement() 負責分號和換行蝇更,beginControlFlow() + endControlFlow() 需要一起使用沪编,相當于{ }

MethodSpec main = MethodSpec.methodBuilder("main")

.addStatement("int total = 0")

.beginControlFlow("for (int i = 0; i < 10; i++)")

.addStatement("total += i")

.endControlFlow()

.build();

還能給生成有參數(shù)的函數(shù)

private MethodSpec computeRange(String name, int from, int to, int op) {

return MethodSpec.methodBuilder(name)

.returns(int.class)

.addStatement("int result = 0")

.beginControlFlow("for (int i = " + from + "; i < " + to + "; i++)")

.addStatement("result = result +" + op + "+ i")

.endControlFlow()

.addStatement("return result")

.build();

}

還有另一種生成有參數(shù)的函數(shù),Literals 直接寫在輸出代碼中,沒有轉義年扩。 它的類型可以是所有基礎類型蚁廓。

private MethodSpec computeRange(String name, int from, int to, int op) {

return MethodSpec.methodBuilder(name)

.returns(int.class)

.addStatement("int result = 0")

.beginControlFlow("for (int i = $L; i < $L; i++)", from, to)

.addStatement("result = result + $L+ i", op)

.endControlFlow()

.addStatement("return result")

.build();

}

然后$S 表示可以一個 string

private static MethodSpec whatsMyName(String name) {

return MethodSpec.methodBuilder(name)

.returns(String.class)

.addStatement("return $S", name)

.build();

}

3.導包

通過 $T 進行映射,會自動import聲明

MethodSpec today = MethodSpec.methodBuilder("today")

.returns(Date.class)

.addStatement("return new $T()", Date.class)

.build();

ClassName 可以識別任何聲明類厨幻。具體看下面的例子:

ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");

ClassName list = ClassName.get("java.util", "List");

ClassName arrayList = ClassName.get("java.util", "ArrayList");

TypeName listOfHoverboards = ParameterizedTypeName.get(list, hoverboard);

MethodSpec beyond = MethodSpec.methodBuilder("beyond")

.returns(listOfHoverboards)

.addStatement("$T result = new $T<>()", listOfHoverboards, arrayList)

.addStatement("result.add(new $T())", hoverboard)

.addStatement("result.add(new $T())", hoverboard)

.addStatement("result.add(new $T())", hoverboard)

.addStatement("return result")

.build();

還有import static

ClassName namedBoards = ClassName.get("com.mattel", "Hoverboard", "Boards");

import static com.mattel.Hoverboard.Boards.*;

還有生成的函數(shù)引用自己生成的函數(shù)

通過$N來引用 hexDigit()方法作為一個參數(shù):

addStatement("result[1] = $N(1)", hexDigit)

4.構造函數(shù)

addParameter(String.class, "greeting")

public HelloWorld(String greeting)

還可以指定類型

addParameter(String.class, "robot", Modifier.FINAL)

5.成員變量Fields

FieldSpec android = FieldSpec.builder(String.class, "android")

.addModifiers(Modifier.PRIVATE, Modifier.FINAL)

.build();

TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")

.addModifiers(Modifier.PUBLIC)

.addField(android)

.addField(String.class, "robot", Modifier.PRIVATE, Modifier.FINAL)

.build();

public class HelloWorld {

private final String android;

private final String robot;

}

6.接口

TypeSpec helloWorld = TypeSpec.interfaceBuilder("HelloWorld")

.addModifiers(Modifier.PUBLIC)

.build();

7.枚舉

TypeSpec helloWorld = TypeSpec.enumBuilder("Roshambo")

.addModifiers(Modifier.PUBLIC)

.addEnumConstant("ROCK")

.addEnumConstant("SCISSORS")

.addEnumConstant("PAPER")

.build();

參考文章

http://blog.csdn.net/crazy1235/article/details/51876192

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末相嵌,一起剝皮案震驚了整個濱河市腿时,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饭宾,老刑警劉巖批糟,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異看铆,居然都是意外死亡徽鼎,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門弹惦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來否淤,“玉大人,你說我怎么就攤上這事棠隐∈眨” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵助泽,是天一觀的道長汁雷。 經(jīng)常有香客問我,道長报咳,這世上最難降的妖魔是什么侠讯? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮暑刃,結果婚禮上厢漩,老公的妹妹穿的比我還像新娘。我一直安慰自己岩臣,他們只是感情好溜嗜,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著架谎,像睡著了一般炸宵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谷扣,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天土全,我揣著相機與錄音,去河邊找鬼会涎。 笑死裹匙,一個胖子當著我的面吹牛,可吹牛的內容都是我干的末秃。 我是一名探鬼主播概页,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼练慕!你這毒婦竟也來了惰匙?” 一聲冷哼從身側響起技掏,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎项鬼,沒想到半個月后零截,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡秃臣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年涧衙,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奥此。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡弧哎,死狀恐怖,靈堂內的尸體忽然破棺而出稚虎,到底是詐尸還是另有隱情撤嫩,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布蠢终,位于F島的核電站序攘,受9級特大地震影響,放射性物質發(fā)生泄漏寻拂。R本人自食惡果不足惜程奠,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望祭钉。 院中可真熱鬧瞄沙,春花似錦、人聲如沸慌核。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽垮卓。三九已至垫桂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間粟按,已是汗流浹背诬滩。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留钾怔,地道東北人碱呼。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓蒙挑,卻偏偏與公主長得像宗侦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子忆蚀,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理矾利,服務發(fā)現(xiàn)姑裂,斷路器,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 背景 一年多以前我在知乎上答了有關LeetCode的問題, 分享了一些自己做題目的經(jīng)驗男旗。 張土汪:刷leetcod...
    土汪閱讀 12,744評論 0 33
  • 1. Java基礎部分 基礎部分的順序:基本語法舶斧,類相關的語法,內部類的語法察皇,繼承相關的語法茴厉,異常的語法,線程的語...
    子非魚_t_閱讀 31,625評論 18 399
  • 在踏浪100學習文案什荣,各種虐心
    TONY先生的假期閱讀 167評論 0 1
  • 且置人間無盡事矾缓,深園長桐自春風。 不可恣愁銷白晝稻爬,靜夜風吹花滿樓嗜闻。 將君還飲此美酒,白駒狩獵西山頭桅锄。 偏聽素湍送白...
    屈喬柯閱讀 332評論 1 1