ASMSupport教程4.12 生成方法调用操作

<p>这一节我们讲如何用ASMSupport生成方法调用的操作,方法调用包括下面四种类型:</p> <ol> <li>调用构造方法 <li>调用静态方法 <li>调用非静态方法 <li>调用当前类的方法 <li>调用父类方法</li></ol> <p>首先我们需要看我们想要生成的类:</p> <p>代码1:</p> <h3> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:8ef33b82-d2bb-4577-8993-178c1b8d44f7" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"><pre class="brush: java; gutter: true; first-line: 1; tab-size: 4; toolbar: true; width: 796px; height: 519px;" style=" width: 796px; height: 519px;overflow: auto;">package generated.operators;

import java.io.PrintStream;

public class MethodInvokeOperatorGenerateExample { public String toString() { return "description is "" + super.toString() + """; }

public String description() { return toString(); }

public static String getDescription(MethodInvokeOperatorGenerateExample obj) { return obj.description(); }

public static void main(String[] args) { MethodInvokeOperatorGenerateExample obj = new MethodInvokeOperatorGenerateExample(); System.out.println("Call static method : " + getDescription(obj)); } }</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div></h3>

<p>这里面包括了所有的方法调用的类型。</p><font style="font-weight: bold"></font> <h3><font style="font-weight: bold">调用构造方法</font></h3> <hr> <p>调用构造方法我们是用的是<strong><font color="#f79646">public final MethodInvoker invokeConstructor(AClass owner, Parameterized... arguments)</font></strong>方法,同样也是ProgramBlock的方法,</p> <p>这个方法有两个参数:</p> <ol> <li>表示需要构造的类,这里我们通过调用getMethodOwner获取当前操作类 <li>表示构造方法的参数。这个参数是个变元参数</li></ol> <p>在代码1中,我们有MethodInvokeOperatorGenerateExample obj = new MethodInvokeOperatorGenerateExample();代码是调用构造方法,那我们对应的asmsupport的代码如下:</p><pre>invokeConstructor(getMethodOwner())</pre> <p>这里有个getMethodOwner()方法,这个方法就是获取当前生成的class或修改的class,由于我们正在创建class MethodInvokeOperatorGenerateExample,所以这里getMethodOwner()获得的AClass就是MethodInvokeOperatorGenerateExample</p> <h3><strong>调用静态方法</strong></h3> <hr> <p>调用静态方法我们使用的是<strong><font color="#f79646">public final MethodInvoker invokeStatic(AClass owner, String methodName, Parameterized... arguments)</font><font color="#000000">方法,</font></strong></p> <p><strong>参数</strong>:</p> <ol> <li>表示调用的静态方法所属的class <li>调用的方法名 <li>表示方法的参数。这个参数是个变元参数</li></ol> <p>在代码1中,getDescription方法就是静态方法,而getDescription(obj)正好是调用静态方法。对应的asmsupport的代码如下:</p> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:e04f2636-f46f-4668-b83c-d56efb64b76e" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"><pre class="brush: java; gutter: true; first-line: 1; tab-size: 4; toolbar: true; width: 796px; height: 35px;" style=" width: 796px; height: 35px;overflow: auto;">invokeStatic(getMethodOwner(), &quot;getDescription&quot;, obj)</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div> <p>这里的obj是上面我们通过构造函数构造的对象,这里作为getDescription的参数。</p> <h3><font style="font-weight: bold">调用非静态方法 </font></h3> <hr> 调用静态方法我们使用的是<strong><font color="#f79646">public final MethodInvoker invoke(Parameterized caller, String methodName, Parameterized... arguments)</font><font color="#000000">方法,</font></strong> <p><strong>参数</strong>:</p> <ol> <li>表示调用的静态方法所属的对象,这里的类型是 Parameterized ,说明这里可以是LocalVariable或者GlobalVariable类型,或者其他的的Parameterized类型 <li>调用的方法名 <li>表示方法的参数。这个参数是个变元参数</li></ol> <p>在代码1中的getDescription方法内,我们调用了”obj.description();”语句,那么对应的asmsupport的代码如下:</p> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:6674f327-f787-40ce-8722-a6021ec32e37" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"><pre class="brush: java; gutter: true; first-line: 1; tab-size: 4; toolbar: true; width: 796px; height: 48px;" style=" width: 796px; height: 48px;overflow: auto;">invoke(argus\[0\], &quot;description&quot;)</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div> <p>这里的argus\[0\]表示当前方法的第一个参数</p> <h3><font style="font-weight: bold">调用当前类的方法和调用父类方法</font></h3><!--EndFragment--> <hr> <p>调用当前类和调用父类的方法其实和调用非静态方法很相似,唯一的区别就是我们传入的第一个参数。在java代码中使用<font color="#ff0000">this和super</font><font color="#000000">关键字表示当前的和父类的,那么我们同样在asmsupport中也有相应的方法:</font></p> <ol> <li><strong>public final ThisVariable getThis():</strong> 返回的<strong>jw.asmsupport.definition.variableThisVariable</strong>对象,将这个对象传入invoke方法的第一个参数。 <li><strong>public final SuperVariable getSuper()</strong>:返回的是<strong>jw.asmsupport.definition.variableSuperVariable</strong>对象,将这个对象传入invoke方法的第一个参数。</li></ol> <p>当然,如果当前类中没有重写父类的方法,我们直接调用getThis()方法并将其返回值传入invoke方法作为调用父类方法。这个和java代码中一样的,比如代码1中的代码:</p> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:f18648a6-5fdb-4fc2-ba06-c938a169a649" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"><pre class="brush: java; gutter: true; first-line: 1; tab-size: 4; toolbar: true; width: 796px; height: 90px;" style=" width: 796px; height: 90px;overflow: auto;">public String description() { return toString(); }</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div> <p>这里面其实就是调用了父类的方法,但是我们这里使用this.toString()或者super.toString()都可以,所以这里我们使用如下asmsupport代码:</p> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:10fb259f-c3aa-4b27-810c-fd855d1ea213" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"><pre class="brush: java; gutter: true; first-line: 1; tab-size: 4; toolbar: true; width: 796px; height: 90px;" style=" width: 796px; height: 90px;overflow: auto;">/\*this.toString()\*/ invoke(getThis(), &quot;toString&quot;) /\*super.toString()\*/ invoke(getSuper(), &quot;toString&quot;)</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div> <h3><font style="font-weight: bold">代码1完整ASMSupport代码:</font></h3> <hr> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:fae928e6-f052-4ee6-ab45-a17630d41028" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"><pre class="brush: java; gutter: true; first-line: 1; tab-size: 4; toolbar: true; width: 796px; height: 2080px;" style=" width: 796px; height: 2080px;overflow: auto;">package example.operators;

import org.objectweb.asm.Opcodes;

import jw.asmsupport.block.method.common.CommonMethodBody; import jw.asmsupport.block.method.common.StaticMethodBody; import jw.asmsupport.clazz.AClass; import jw.asmsupport.clazz.AClassFactory; import jw.asmsupport.creator.ClassCreator; import jw.asmsupport.definition.value.Value; import jw.asmsupport.definition.variable.LocalVariable; import jw.asmsupport.operators.method.MethodInvoker;

import example.AbstractExample;

public class MethodInvokeOperatorGenerate extends AbstractExample {

1/** 2 * @param args 3 */ 4public static void main(String[] args) { 5 6 ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC , &quot;generated.operators.MethodInvokeOperatorGenerateExample&quot;, null, null); 7 8 creator.createMethod(&quot;toString&quot;, null, null, AClass.STRING_ACLASS, null, Opcodes.ACC_PUBLIC, new CommonMethodBody(){ 9 10 @Override 11 public void generateBody(LocalVariable... argus) { 12 //通常我们将super看作是一个变量所以我们用invoke(Parameterized caller, String methodName, Parameterized... arguments) 13 //方法实现super.xxxx。通过getSuper方法获取super变量 14 MethodInvoker superToString = invoke(getSuper(), &quot;toString&quot;); 15 runReturn(append(Value.value(&quot;description is \&quot;&quot;), superToString, Value.value(&quot;\&quot;&quot;))); 16 } 17 18 }); 19 20 /** 21 * 实现如下方法 22 * public String description(){ 23 * return toString(); 24 * } 25 * 26 */ 27 creator.createMethod(&quot;description&quot;, null, null, AClass.STRING_ACLASS, null, Opcodes.ACC_PUBLIC, new CommonMethodBody(){ 28 29 @Override 30 public void generateBody(LocalVariable... argus) { 31 /** 32 * 这里和调用super.xxx是一样的。调用当前类中的非静态方法都是通过 33 * invoke(Parameterized caller, String methodName, Parameterized... arguments)方法调用。 34 * 通过getThis方法获取this变量 35 */ 36 runReturn(invoke(getThis(), &quot;toString&quot;)); 37 } 38 39 }); 40 41 /** 42 * 生成如下方法的字节码: 43 * public static String getDescription(MyObject obj){ 44 * return obj.description(); 45 * } 46 */ 47 creator.createStaticMethod(&quot;getDescription&quot;, new AClass[]{creator.getCurrentClass()}, new String[]{&quot;obj&quot;}, AClass.STRING_ACLASS, null, 48 Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, new StaticMethodBody(){ 49 50 @Override 51 public void generateBody(LocalVariable... argus) { 52 /** 53 * 和上面。 54 * 这里argus[0]就是我们定义的参数obj。如果需要传递参数可以直接在 55 * 方法调用的时候添加需要传递的参数,因为这是个变元方法 56 */ 57 runReturn(invoke(argus[0], &quot;description&quot;)); 58 } 59 }); 60 61 /** 62 * public static void main(String[] args){ 63 * MyObject obj = new MyObject(); 64 * System.out.println(&quot;Call static method : &quot; + MyObject.getDescription(obj)); 65 * } 66 */ 67 creator.createStaticMethod(&quot;main&quot;, new AClass[]{AClassFactory.getProductClass(String[].class)}, new String[]{&quot;args&quot;}, null, null, 68 Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, new StaticMethodBody(){ 69 70 @Override 71 public void generateBody(LocalVariable... argus) { 72 /** 73 * 首先调用构造方法生成MethodInvokeOperatorGenerateExample obj = new MethodInvokeOperatorGenerateExample(); 74 * 通过invokeConstructor方法实现调用构造方法 75 * 这个方法后两个参数。 76 * 1.表示需要构造的类,这里我们通过调用getMethodOwner获取当前操作类 77 * 2.表示构造方法的参数。这个参数是个变元参数 78 */ 79 LocalVariable obj = createVariable(&quot;obj&quot;, getMethodOwner(), false, invokeConstructor(getMethodOwner())); 80 81 /** 82 * 实现System.out.println(&quot;Call static method : &quot; + MyObject.getDescription(obj)); 83 * 这里将学习到如何生成调用静态方法 84 * 85 * 调用静态方法是通过invokeStatic(AClass owner, String methodName, Parameterized... arguments) 86 * 实现的。 87 * 这个方法有三个参数 88 * 1.通过那个Class调用静态方法。 89 * 2.静态方法的名称 90 * 3.参数 91 */ 92 MethodInvoker getDescriptionInvoker = invokeStatic(getMethodOwner(), &quot;getDescription&quot;, obj); 93 94 invoke(systemOut, &quot;println&quot;, append(Value.value(&quot;Call static method : &quot;), getDescriptionInvoker)); 95 96 runReturn(); 97 } 98 }); 99 generate(creator); 100}

} </pre></div> 更多教程

更多教程

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Java日期时间API系列31

  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前

java反射大全

作者对反射的理解:方法的调用(正常的调用:对象.方法()。反射调用方法:方法.对象())静态属性的调用(正常的调用:类.属性。反射调用:属性.类)常见反射的用法:        1.通过反射获取类Class<?demo1Class

ASMSupport教程4.12 生成方法调用操作 - HelloWorld