<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ù):如何修改語法樹?

          共 16390字,需瀏覽 33分鐘

           ·

          2021-10-08 22:06

          作者:不學(xué)無數(shù)的程序員?

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


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

          JCTree的介紹

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

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

          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é)點
          2. JCMethodDecl:方法定義語法樹節(jié)點

          3. JCModifiers:訪問標(biāo)志語法樹節(jié)點

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


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

          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)建訪問標(biāo)志語法樹節(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:訪問標(biāo)志
          2. annotations:注解列表

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

          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:訪問標(biāo)志,可以通過TreeMaker.Modifiers來創(chuàng)建
          2. name:類名
          3. typarams:泛型參數(shù)列表
          4. extending:父類
          5. implementing:實現(xiàn)的接口
          6. defs:類定義的詳細(xì)語句,包括字段、方法的定義等等

          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:訪問標(biāo)志
          2. name:方法名
          3. restype:返回類型
          4. typarams:泛型參數(shù)列表
          5. params:參數(shù)列表
          6. thrown:異常聲明列表
          7. body:方法體
          8. defaultValue:默認(rèn)方法(可能是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:訪問標(biāo)志
          2. name:參數(shù)名稱
          3. vartype:類型
          4. init:初始化語句
          5. v:變量符號

          TreeMaker.Ident

          TreeMaker.Ident用于創(chuàng)建標(biāo)識符語法樹節(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:.運算符左邊的表達(dá)式
          2. selector:.運算符右邊的表達(dá)式

          下面給出一個例子,一語句生成的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:賦值語句左邊表達(dá)式
          2. rhs:賦值語句右邊表達(dá)式

          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:訪問標(biāo)志
          2. stats:語句列表

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

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

          public?class?List?extends?AbstractCollection?implements?java.util.List?{
          ????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?extends?AbstractQueue?{

          ????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)

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

          無參無返回值

          我們可以利用上面講到的MethodDef方法進(jìn)行生成

          /*
          ????無參無返回值的方法生成
          ????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方法進(jìn)行生成

          /*
          ????無參無返回值的方法生成
          ????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)?br>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)?br>????????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)?br>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)?br>????????com.sun.tools.javac.util.List.nil(),
          ????????testBody3,
          ????????null
          );

          特殊的

          我們學(xué)完了如何進(jìn)行定義參數(shù),如何進(jìn)行定義方法,其實還有好多語句需要學(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é)

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

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

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

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


          1.?老王,快給你的 Spring Boot 做個埋點監(jiān)控吧!

          2.?牛逼,國產(chǎn)開源的遠(yuǎn)程桌面火了,只有9MB,支持自建中繼器!

          3.?Java 數(shù)組中new Object[5]語句是否創(chuàng)建了5個對象?

          4.?Java 8 一行代碼解決了空指針問題,太厲害了...

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點“在看”,關(guān)注公眾號并回復(fù)?Java?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。

          謝謝支持喲 (*^__^*)

          瀏覽 54
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                    国免费黄片 | 婷婷五月六月丁香 | 婷婷天网站 | 十八禁黄网站 | 夏目あきら被续侵犯7天 |