<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java 中的屠龍之術(shù):如何修改語法樹?

          共 16335字,需瀏覽 33分鐘

           ·

          2021-11-12 20:03

          來源:my.oschina.net/u/
          4030990/blog/3211858



            在網(wǎng)上關(guān)于如何修改Java的抽象語法樹的相關(guān)API文檔并不多,于是本篇記錄一下相關(guān)的知識點,以便隨后查閱。

            JCTree的介紹

            JCTree是語法樹元素的基類,包含一個重要的字段pos,該字段用于指明當前語法樹節(jié)點(JCTree)在語法樹中的位置,因此我們不能直接用new關(guān)鍵字來創(chuàng)建語法樹節(jié)點,即使創(chuàng)建了也沒有意義。

            此外,結(jié)合訪問者模式,將數(shù)據(jù)結(jié)構(gòu)與數(shù)據(jù)的處理進行解耦,部分源碼如下:

            public?abstract?class?JCTree?implements?Tree,?Cloneable,?DiagnosticPosition?{

            ????public?int?pos?=?-1;

            ????...

            ????public?abstract?void?accept(JCTree.Visitor?visitor);

            ????...
            }

            我們可以看到JCTree是一個抽象類,這里重點介紹幾個JCTree的子類

            1. JCStatement:聲明 語法樹節(jié)點,常見的子類如下



              • JCBlock:語句塊 語法樹節(jié)點
            • JCReturn:return語句 語法樹節(jié)點
            • JCClassDecl:類定義 語法樹節(jié)點
            • JCVariableDecl:字段/變量定義 語法樹節(jié)點
            1. JCMethodDecl:方法定義 語法樹節(jié)點

            2. JCModifiers:訪問標志 語法樹節(jié)點

            3. JCExpression:表達式 語法樹節(jié)點,常見的子類如下



              • JCAssign:賦值語句 語法樹節(jié)點
            • JCIdent:標識符 語法樹節(jié)點,可以是變量,類型,關(guān)鍵字等等

            推薦下自己做的 Spring Boot 的實戰(zhàn)項目:

            https://github.com/YunaiV/ruoyi-vue-pro

            TreeMaker介紹

            TreeMaker用于創(chuàng)建一系列的語法樹節(jié)點,我們上面說了創(chuàng)建JCTree不能直接使用new關(guān)鍵字來創(chuàng)建,所以Java為我們提供了一個工具,就是TreeMaker,它會在創(chuàng)建時為我們創(chuàng)建的JCTree對象設(shè)置pos字段,所以必須使用上下文相關(guān)的TreeMaker對象來創(chuàng)建語法樹節(jié)點。

            具體的API介紹可以參照,TreeMakerAPI,接下來著重介紹一下常用的幾個方法。

            TreeMaker.Modifiers

            TreeMaker.Modifiers方法用于創(chuàng)建訪問標志 語法樹節(jié)點(JCModifiers),源碼如下

            public?JCModifiers?Modifiers(long?flags)?{
            ????return?Modifiers(flags,?List.nil());
            }

            public?JCModifiers?Modifiers(long?flags,
            ????List?annotations)
            ?
            {
            ????????JCModifiers?tree?=?new?JCModifiers(flags,?annotations);
            ????????boolean?noFlags?=?(flags?&?(Flags.ModifierFlags?|?Flags.ANNOTATION))?==?0;
            ????????tree.pos?=?(noFlags?&&?annotations.isEmpty())???Position.NOPOS?:?pos;
            ????????return?tree;
            }
            1. flags:訪問標志
            2. annotations:注解列表

            其中flags可以使用枚舉類com.sun.tools.javac.code.Flags來表示,例如我們可以這樣用,就生成了下面的訪問標志了。

            treeMaker.Modifiers(Flags.PUBLIC?+?Flags.STATIC?+?Flags.FINAL);

            public?static?final

            TreeMaker.ClassDef

            TreeMaker.ClassDef用于創(chuàng)建類定義 語法樹節(jié)點(JCClassDecl),源碼如下:

            public?JCClassDecl?ClassDef(JCModifiers?mods,
            ????Name?name,
            ????List?typarams,
            ????JCExpression?extending,
            ????List?implementing,
            ????List?defs)
            ?
            {
            ????????JCClassDecl?tree?=?new?JCClassDecl(mods,
            ?????????????????????????????????????name,
            ?????????????????????????????????????typarams,
            ?????????????????????????????????????extending,
            ?????????????????????????????????????implementing,
            ?????????????????????????????????????defs,
            ?????????????????????????????????????null);
            ????????tree.pos?=?pos;
            ????????return?tree;
            }
            1. mods:訪問標志,可以通過TreeMaker.Modifiers來創(chuàng)建
            2. name:類名
            3. typarams:泛型參數(shù)列表
            4. extending:父類
            5. implementing:實現(xiàn)的接口
            6. defs:類定義的詳細語句,包括字段、方法的定義等等

            TreeMaker.MethodDef

            TreeMaker.MethodDef用于創(chuàng)建方法定義 語法樹節(jié)點(JCMethodDecl),源碼如下

            public?JCMethodDecl?MethodDef(JCModifiers?mods,
            ????Name?name,
            ????JCExpression?restype,
            ????List?typarams,
            ????List?params,
            ????List?thrown,
            ????JCBlock?body,
            ????JCExpression?defaultValue)
            ?
            {
            ????????JCMethodDecl?tree?=?new?JCMethodDecl(mods,
            ???????????????????????????????????????name,
            ???????????????????????????????????????restype,
            ???????????????????????????????????????typarams,
            ???????????????????????????????????????params,
            ???????????????????????????????????????thrown,
            ???????????????????????????????????????body,
            ???????????????????????????????????????defaultValue,
            ???????????????????????????????????????null);
            ????????tree.pos?=?pos;
            ????????return?tree;
            }

            public?JCMethodDecl?MethodDef(MethodSymbol?m,
            ????Type?mtype,
            ????JCBlock?body)
            ?
            {
            ????????return?(JCMethodDecl)
            ????????????new?JCMethodDecl(
            ????????????????Modifiers(m.flags(),?Annotations(m.getAnnotationMirrors())),
            ????????????????m.name,
            ????????????????Type(mtype.getReturnType()),
            ????????????????TypeParams(mtype.getTypeArguments()),
            ????????????????Params(mtype.getParameterTypes(),?m),
            ????????????????Types(mtype.getThrownTypes()),
            ????????????????body,
            ????????????????null,
            ????????????????m).setPos(pos).setType(mtype);
            }
            1. mods:訪問標志
            2. name:方法名
            3. restype:返回類型
            4. typarams:泛型參數(shù)列表
            5. params:參數(shù)列表
            6. thrown:異常聲明列表
            7. body:方法體
            8. defaultValue:默認方法(可能是interface中的哪個default)
            9. m:方法符號
            10. mtype:方法類型。包含多種類型,泛型參數(shù)類型、方法參數(shù)類型、異常參數(shù)類型、返回參數(shù)類型。

            返回類型restype填寫null或者treeMaker.TypeIdent(TypeTag.VOID)都代表返回void類型。

            TreeMaker.VarDef

            TreeMaker.VarDef用于創(chuàng)建字段/變量定義 語法樹節(jié)點(JCVariableDecl),源碼如下

            public?JCVariableDecl?VarDef(JCModifiers?mods,
            ????Name?name,
            ????JCExpression?vartype,
            ????JCExpression?init)
            ?
            {
            ????????JCVariableDecl?tree?=?new?JCVariableDecl(mods,?name,?vartype,?init,?null);
            ????????tree.pos?=?pos;
            ????????return?tree;
            }

            public?JCVariableDecl?VarDef(VarSymbol?v,
            ????JCExpression?init)
            ?
            {
            ????????return?(JCVariableDecl)
            ????????????new?JCVariableDecl(
            ????????????????Modifiers(v.flags(),?Annotations(v.getAnnotationMirrors())),
            ????????????????v.name,
            ????????????????Type(v.type),
            ????????????????init,
            ????????????????v).setPos(pos).setType(v.type);
            }
            1. mods:訪問標志
            2. name:參數(shù)名稱
            3. vartype:類型
            4. init:初始化語句
            5. v:變量符號

            TreeMaker.Ident

            TreeMaker.Ident用于創(chuàng)建標識符 語法樹節(jié)點(JCIdent),源碼如下

            public?JCIdent?Ident(Name?name)?{
            ????????JCIdent?tree?=?new?JCIdent(name,?null);
            ????????tree.pos?=?pos;
            ????????return?tree;
            }

            public?JCIdent?Ident(Symbol?sym)?{
            ????????return?(JCIdent)new?JCIdent((sym.name?!=?names.empty)
            ??????????????????????????????????sym.name
            ????????????????????????????????:?sym.flatName(),?sym)
            ????????????.setPos(pos)
            ????????????.setType(sym.type);
            }

            public?JCExpression?Ident(JCVariableDecl?param)?{
            ????????return?Ident(param.sym);
            }

            TreeMaker.Return

            TreeMaker.Return用于創(chuàng)建return語句 (JCReturn),源碼如下

            public?JCReturn?Return(JCExpression?expr)?{
            ????????JCReturn?tree?=?new?JCReturn(expr);
            ????????tree.pos?=?pos;
            ????????return?tree;
            }

            TreeMaker.Select

            TreeMaker.Select用于創(chuàng)建域訪問/方法訪問 (這里的方法訪問只是取到名字,方法的調(diào)用需要用TreeMaker.Apply)語法樹節(jié)點(JCFieldAccess),源碼如下

            public?JCFieldAccess?Select(JCExpression?selected,
            ????Name?selector)
            ?
            {
            ????????JCFieldAccess?tree?=?new?JCFieldAccess(selected,?selector,?null);
            ????????tree.pos?=?pos;
            ????????return?tree;
            }

            public?JCExpression?Select(JCExpression?base,
            ????Symbol?sym)
            ?
            {
            ????????return?new?JCFieldAccess(base,?sym.name,?sym).setPos(pos).setType(sym.type);
            }
            1. selected:.運算符左邊的表達式
            2. selector:.運算符右邊的表達式

            下面給出一個例子,一語句生成的Java語句就是二語句

            一.?TreeMaker.Select(treeMaker.Ident(names.fromString("this")),?names.fromString("name"));

            二.?this.name

            TreeMaker.NewClass

            TreeMaker.NewClass用于創(chuàng)建new語句 語法樹節(jié)點(JCNewClass),源碼如下:

            public?JCNewClass?NewClass(JCExpression?encl,
            ????List?typeargs,
            ????JCExpression?clazz,
            ????List?args,
            ????JCClassDecl?def)
            ?
            {
            ????????JCNewClass?tree?=?new?JCNewClass(encl,?typeargs,?clazz,?args,?def);
            ????????tree.pos?=?pos;
            ????????return?tree;
            }
            1. encl:不太明白此參數(shù)的含義,我看很多例子中此參數(shù)都設(shè)置為null
            2. typeargs:參數(shù)類型列表
            3. clazz:待創(chuàng)建對象的類型
            4. args:參數(shù)列表
            5. def:類定義

            TreeMaker.Apply

            TreeMaker.Apply用于創(chuàng)建方法調(diào)用 語法樹節(jié)點(JCMethodInvocation),源碼如下:

            public?JCMethodInvocation?Apply(List?typeargs,
            ????JCExpression?fn,
            ????List?args)
            ?
            {
            ????????JCMethodInvocation?tree?=?new?JCMethodInvocation(typeargs,?fn,?args);
            ????????tree.pos?=?pos;
            ????????return?tree;
            }
            1. typeargs:參數(shù)類型列表
            2. fn:調(diào)用語句
            3. args:參數(shù)列表

            TreeMaker.Assign

            TreeMaker.Assign用戶創(chuàng)建賦值語句 語法樹節(jié)點(JCAssign),源碼如下:

            ublic?JCAssign?Assign(JCExpression?lhs,
            ????JCExpression?rhs)
            ?
            {
            ????????JCAssign?tree?=?new?JCAssign(lhs,?rhs);
            ????????tree.pos?=?pos;
            ????????return?tree;
            }
            1. lhs:賦值語句左邊表達式
            2. rhs:賦值語句右邊表達式

            TreeMaker.Exec

            TreeMaker.Exec用于創(chuàng)建可執(zhí)行語句 語法樹節(jié)點(JCExpressionStatement),源碼如下:

            public?JCExpressionStatement?Exec(JCExpression?expr)?{
            ????????JCExpressionStatement?tree?=?new?JCExpressionStatement(expr);
            ????????tree.pos?=?pos;
            ????????return?tree;
            }

            TreeMaker.Apply以及TreeMaker.Assign就需要外面包一層TreeMaker.Exec來獲得一個JCExpressionStatement。

            TreeMaker.Block

            TreeMaker.Block用于創(chuàng)建組合語句 的語法樹節(jié)點(JCBlock),源碼如下:

            public?JCBlock?Block(long?flags,
            ????List?stats)
            ?
            {
            ????????JCBlock?tree?=?new?JCBlock(flags,?stats);
            ????????tree.pos?=?pos;
            ????????return?tree;
            }
            1. flags:訪問標志
            2. stats:語句列表

            推薦下自己做的 Spring Cloud 的實戰(zhàn)項目:

            https://github.com/YunaiV/onemall

            com.sun.tools.javac.util.List介紹

            在我們操作抽象語法樹的時候,有時會涉及到關(guān)于List的操作,但是這個List不是我們經(jīng)常使用的java.util.List而是com.sun.tools.javac.util.List,這個List比較奇怪,是一個鏈式的結(jié)構(gòu),有頭結(jié)點和尾節(jié)點,但是只有尾節(jié)點是一個List,這里作為了解就行了。

            public?class?List<A>?extends?AbstractCollection<A>?implements?java.util.List<A>?{
            ????public?A?head;
            ????public?List?tail;
            ????private?static?final?List?EMPTY_LIST?=?new?List((Object)null,?(List)null)?{
            ????????public?List?setTail(List?var1)?{
            ????????????throw?new?UnsupportedOperationException();
            ????????}

            ????????public?boolean?isEmpty()?{
            ????????????return?true;
            ????????}
            ????};

            ????List(A?head,?List?tail)?{
            ????????this.tail?=?tail;
            ????????this.head?=?head;
            ????}

            ????public?static?
            ?List?nil()?{
            ????????return?EMPTY_LIST;
            ????}

            ????public?List
            ?prepend(A?var1)?{
            ????????return?new?List(var1,?this);
            ????}

            ????public?List
            ?append(A?var1)?{
            ????????return?of(var1).prependList(this);
            ????}

            ????public?static?
            ?List?of(A?var0)?{
            ????????return?new?List(var0,?nil());
            ????}

            ????public?static?
            ?List?of(A?var0,?A?var1)?{
            ????????return?new?List(var0,?of(var1));
            ????}

            ????public?static?
            ?List?of(A?var0,?A?var1,?A?var2)?{
            ????????return?new?List(var0,?of(var1,?var2));
            ????}

            ????public?static?
            ?List?of(A?var0,?A?var1,?A?var2,?A...?var3)?{
            ????????return?new?List(var0,?new?List(var1,?new?List(var2,?from(var3))));
            ????}

            ????...
            }

            com.sun.tools.javac.util.ListBuffer

            由于com.sun.tools.javac.util.List使用起來不方便,所以又在其上面封裝了一層,這個封裝類是ListBuffer,此類的操作和我們平時經(jīng)常使用的java.util.List用法非常類似。

            public?class?ListBuffer<A>?extends?AbstractQueue<A>?{

            ????public?static??ListBuffer?of(T?x)?{
            ????????ListBuffer?lb?=?new?ListBuffer();
            ????????lb.add(x);
            ????????return?lb;
            ????}

            ????/**?The?list?of?elements?of?this?buffer.
            ?????*/

            ????private?List?elems;

            ????/**?A?pointer?pointing?to?the?last?element?of?'elems'?containing?data,
            ?????*??or?null?if?the?list?is?empty.
            ?????*/

            ????private?List
            ?last;

            ????/**?The?number?of?element?in?this?buffer.
            ?????*/

            ????private?int?count;

            ????/**?Has?a?list?been?created?from?this?buffer?yet?
            ?????*/

            ????private?boolean?shared;

            ????/**?Create?a?new?initially?empty?list?buffer.
            ?????*/

            ????public?ListBuffer()?{
            ????????clear();
            ????}

            ????/**?Append?an?element?to?buffer.
            ?????*/

            ????public?ListBuffer
            ?append(A?x)?{
            ????????x.getClass();?//?null?check
            ????????if?(shared)?copy();
            ????????List
            ?newLast?=?List.of(x);
            ????????if?(last?!=?null)?{
            ????????????last.tail?=?newLast;
            ????????????last?=?newLast;
            ????????}?else?{
            ????????????elems?=?last?=?newLast;
            ????????}
            ????????count++;
            ????????return?this;
            ????}
            ????........
            }

            com.sun.tools.javac.util.Names介紹

            這個是為我們創(chuàng)建名稱的一個工具類,無論是類、方法、參數(shù)的名稱都需要通過此類來創(chuàng)建。它里面經(jīng)常被使用到的一個方法就是fromString(),一般使用方法如下所示。

            Names?names??=?new?Names()
            names.?fromString("setName");

            實戰(zhàn)演練

            上面我們大概了解了如何操作抽象語法樹,接下來我們就來寫幾個真實的案例加深理解。

            變量相關(guān)

            在類中我們經(jīng)常操作的參數(shù)就是變量,那么如何使用抽象語法樹的特性為我們操作變量呢?接下來我們就將一些對于變量的一些操作。

            生成變量

            例如生成private String age;這樣一個變量,借用我們上面講的VarDef方法

            //?生成參數(shù)?例如:private String age;
            treeMaker.VarDef(treeMaker.Modifiers(Flags.PRIVATE),?names.fromString("age"),?treeMaker.Ident(names.fromString("String")),?null);

            對變量賦值

            例如我們想生成private String name = "BuXueWuShu",還是利用VarDef方法

            //?private?String?name?=?"BuXueWuShu"
            treeMaker.VarDef(treeMaker.Modifiers(Flags.PRIVATE),names.fromString("name"),treeMaker.Ident(names.fromString("String")),treeMaker.Literal("BuXueWuShu"))

            兩個字面量相加

            例如我們生成String add = "a" + "b";,借用我們上面講的Exec方法和Assign方法

            //?add?=?"a"+"b"
            treeMaker.Exec(treeMaker.Assign(treeMaker.Ident(names.fromString("add")),treeMaker.Binary(JCTree.Tag.PLUS,treeMaker.Literal("a"),treeMaker.Literal("b"))))

            +=語法

            例如我們想生成add += "test",則和上面字面量差不多。

            //?add+="test"
            treeMaker.Exec(treeMaker.Assignop(JCTree.Tag.PLUS_ASG,?treeMaker.Ident(names.fromString("add")),?treeMaker.Literal("test")))

            ++語法

            例如想生成++i

            treeMaker.Exec(treeMaker.Unary(JCTree.Tag.PREINC,treeMaker.Ident(names.fromString("i"))))

            方法相關(guān)

            我們對于變量進行了操作,那么基本上都是要生成方法的,那么如何對方法進行生成和操作呢?我們接下來演示一下關(guān)于方法相關(guān)的操作方法。

            無參無返回值

            我們可以利用上面講到的MethodDef方法進行生成

            /*
            ????無參無返回值的方法生成
            ????public?void?test(){

            ????}
            ?*/

            //?定義方法體
            ListBuffer?testStatement?=?new?ListBuffer<>();
            JCTree.JCBlock?testBody?=?treeMaker.Block(0,?testStatement.toList());
            ????
            JCTree.JCMethodDecl?test?=?treeMaker.MethodDef(
            ????????treeMaker.Modifiers(Flags.PUBLIC),?//?方法限定值
            ????????names.fromString("test"),?//?方法名
            ????????treeMaker.Type(new?Type.JCVoidType()),?//?返回類型
            ????????com.sun.tools.javac.util.List.nil(),
            ????????com.sun.tools.javac.util.List.nil(),
            ????????com.sun.tools.javac.util.List.nil(),
            ????????testBody,?//?方法體
            ????????null
            );

            有參無返回值

            我們可以利用上面講到的MethodDef方法進行生成

            /*
            ????無參無返回值的方法生成
            ????public?void?test2(String?name){
            ????????name?=?"xxxx";
            ????}
            ?*/

            ListBuffer?testStatement2?=?new?ListBuffer<>();
            testStatement2.append(treeMaker.Exec(treeMaker.Assign(treeMaker.Ident(names.fromString("name")),treeMaker.Literal("xxxx"))));
            JCTree.JCBlock?testBody2?=?treeMaker.Block(0,?testStatement2.toList());

            //?生成入?yún)?/span>
            JCTree.JCVariableDecl?param?=?treeMaker.VarDef(treeMaker.Modifiers(Flags.PARAMETER),?names.fromString("name"),treeMaker.Ident(names.fromString("String")),?null);
            com.sun.tools.javac.util.List?parameters?=?com.sun.tools.javac.util.List.of(param);

            JCTree.JCMethodDecl?test2?=?treeMaker.MethodDef(
            ????????treeMaker.Modifiers(Flags.PUBLIC),?//?方法限定值
            ????????names.fromString("test2"),?//?方法名
            ????????treeMaker.Type(new?Type.JCVoidType()),?//?返回類型
            ????????com.sun.tools.javac.util.List.nil(),
            ????????parameters,?//?入?yún)?/span>
            ????????com.sun.tools.javac.util.List.nil(),
            ????????testBody2,
            ????????null
            );

            有參有返回值

            ?/*
            ????有參有返回值
            ????public?String?test3(String?name){
            ???????return?name;
            ????}
            ?*/


            ListBuffer?testStatement3?=?new?ListBuffer<>();
            testStatement3.append(treeMaker.Return(treeMaker.Ident(names.fromString("name"))));
            JCTree.JCBlock?testBody3?=?treeMaker.Block(0,?testStatement3.toList());

            //?生成入?yún)?/span>
            JCTree.JCVariableDecl?param3?=?treeMaker.VarDef(treeMaker.Modifiers(Flags.PARAMETER),?names.fromString("name"),treeMaker.Ident(names.fromString("String")),?null);
            com.sun.tools.javac.util.List?parameters3?=?com.sun.tools.javac.util.List.of(param3);

            JCTree.JCMethodDecl?test3?=?treeMaker.MethodDef(
            ????????treeMaker.Modifiers(Flags.PUBLIC),?//?方法限定值
            ????????names.fromString("test4"),?//?方法名
            ????????treeMaker.Ident(names.fromString("String")),?//?返回類型
            ????????com.sun.tools.javac.util.List.nil(),
            ????????parameters3,?//?入?yún)?/span>
            ????????com.sun.tools.javac.util.List.nil(),
            ????????testBody3,
            ????????null
            );

            特殊的

            我們學(xué)完了如何進行定義參數(shù),如何進行定義方法,其實還有好多語句需要學(xué)習(xí),例如如何生成new語句,如何生成方法調(diào)用的語句,如何生成if語句。j接下來我們就學(xué)習(xí)一些比較特殊的語法。

            new一個對象

            //?創(chuàng)建一個new語句?CombatJCTreeMain?combatJCTreeMain?=?new?CombatJCTreeMain();
            JCTree.JCNewClass?combatJCTreeMain?=?treeMaker.NewClass(
            ????????null,
            ????????com.sun.tools.javac.util.List.nil(),
            ????????treeMaker.Ident(names.fromString("CombatJCTreeMain")),
            ????????com.sun.tools.javac.util.List.nil(),
            ????????null
            );
            JCTree.JCVariableDecl?jcVariableDecl1?=?treeMaker.VarDef(
            ????????treeMaker.Modifiers(Flags.PARAMETER),
            ????????names.fromString("combatJCTreeMain"),
            ????????treeMaker.Ident(names.fromString("CombatJCTreeMain")),
            ????????combatJCTreeMain
            );

            方法調(diào)用(無參)

            JCTree.JCExpressionStatement?exec?=?treeMaker.Exec(
            ????????treeMaker.Apply(
            ????????????????com.sun.tools.javac.util.List.nil(),
            ????????????????treeMaker.Select(
            ????????????????????????treeMaker.Ident(names.fromString("combatJCTreeMain")),?//?.?左邊的內(nèi)容
            ????????????????????????names.fromString("test")?//?.?右邊的內(nèi)容
            ????????????????),
            ????????????????com.sun.tools.javac.util.List.nil()
            ????????)
            );

            方法調(diào)用(有參)

            //?創(chuàng)建一個方法調(diào)用?combatJCTreeMain.test2("hello?world!");
            JCTree.JCExpressionStatement?exec2?=?treeMaker.Exec(
            ????????treeMaker.Apply(
            ????????????????com.sun.tools.javac.util.List.nil(),
            ????????????????treeMaker.Select(
            ????????????????????????treeMaker.Ident(names.fromString("combatJCTreeMain")),?//?.?左邊的內(nèi)容
            ????????????????????????names.fromString("test2")?//?.?右邊的內(nèi)容
            ????????????????),
            ????????????????com.sun.tools.javac.util.List.of(treeMaker.Literal("hello?world!"))?//?方法中的內(nèi)容
            ????????)
            );

            if語句

            /*
            ????創(chuàng)建一個if語句
            ????if("BuXueWuShu".equals(name)){
            ????????add?=?"a"?+?"b";
            ????}else{
            ????????add?+=?"test";
            ????}
            ?*/

            //?"BuXueWuShu".equals(name)
            JCTree.JCMethodInvocation?apply?=?treeMaker.Apply(
            ????????com.sun.tools.javac.util.List.nil(),
            ????????treeMaker.Select(
            ????????????????treeMaker.Literal("BuXueWuShu"),?//?.?左邊的內(nèi)容
            ????????????????names.fromString("equals")?//?.?右邊的內(nèi)容
            ????????),
            ????????com.sun.tools.javac.util.List.of(treeMaker.Ident(names.fromString("name")))
            );
            //??add?=?"a"?+?"b"
            JCTree.JCExpressionStatement?exec3?=?treeMaker.Exec(treeMaker.Assign(treeMaker.Ident(names.fromString("add")),?treeMaker.Binary(JCTree.Tag.PLUS,?treeMaker.Literal("a"),?treeMaker.Literal("b"))));
            //??add?+=?"test"
            JCTree.JCExpressionStatement?exec1?=?treeMaker.Exec(treeMaker.Assignop(JCTree.Tag.PLUS_ASG,?treeMaker.Ident(names.fromString("add")),?treeMaker.Literal("test")));

            JCTree.JCIf?anIf?=?treeMaker.If(
            ????????apply,?//?if語句里面的判斷語句
            ????????exec3,?//?條件成立的語句
            ????????exec1??//?條件不成立的語句
            );

            源碼地址:https://github.com/modouxiansheng/Doraemon

            總結(jié)

            紙上得來終覺淺,絕知此事要躬行。

            希望大家看完此篇文章能夠自己在本機上自己試驗一下。

            自己設(shè)置幾個參數(shù),自己學(xué)的Lombok學(xué)著生成一下get、set方法,雖然本篇知識在日常開發(fā)中基本上不會用到,但是萬一用到了這些知識那么別人不會而你會,差距其實就慢慢的給拉開了。

            本篇涉及到的所有代碼都在github上面有,拉下來以后全局搜CombatJCTreeProcessor類就可以看到了。


            關(guān)注公眾號【Java技術(shù)江湖】后回復(fù)“PDF”即可領(lǐng)取200+頁的《Java工程師面試指南》

            強烈推薦,幾乎涵蓋所有Java工程師必知必會的知識點,不管是復(fù)習(xí)還是面試,都很實用。



            瀏覽 28
            點贊
            評論
            收藏
            分享

            手機掃一掃分享

            分享
            舉報
            評論
            圖片
            表情
            推薦
            點贊
            評論
            收藏
            分享

            手機掃一掃分享

            分享
            舉報
            <kbd id="afajh"><form id="afajh"></form></kbd>
            <strong id="afajh"><dl id="afajh"></dl></strong>
              <del id="afajh"><form id="afajh"></form></del>
                  1. <th id="afajh"><progress id="afajh"></progress></th>
                    <b id="afajh"><abbr id="afajh"></abbr></b>
                      <th id="afajh"><progress id="afajh"></progress></th>
                      极品人妻无码 | 天天操91AV | 国产日韩一级片 | 日本精品视频在线观看 | 美穴在线观看 |