<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;java
import java.io.PrintStream;web
public class MethodInvokeOperatorGenerateExample { public String toString() { return "description is "" + super.toString() + """; }app
public String description() { return toString(); }ide
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>this
<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>code
<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(), "getDescription", 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], "description")</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>orm
<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(), "toString") /*super.toString()*/ invoke(getSuper(), "toString")</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 {
/** * @param args */ public static void main(String[] args) { ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC , "generated.operators.MethodInvokeOperatorGenerateExample", null, null); creator.createMethod("toString", null, null, AClass.STRING_ACLASS, null, Opcodes.ACC_PUBLIC, new CommonMethodBody(){ @Override public void generateBody(LocalVariable... argus) { //一般咱们将super看做是一个变量因此咱们用invoke(Parameterized caller, String methodName, Parameterized... arguments) //方法实现super.xxxx。经过getSuper方法获取super变量 MethodInvoker superToString = invoke(getSuper(), "toString"); runReturn(append(Value.value("description is \""), superToString, Value.value("\""))); } }); /** * 实现以下方法 * public String description(){ * return toString(); * } * */ creator.createMethod("description", null, null, AClass.STRING_ACLASS, null, Opcodes.ACC_PUBLIC, new CommonMethodBody(){ @Override public void generateBody(LocalVariable... argus) { /** * 这里和调用super.xxx是同样的。调用当前类中的非静态方法都是经过 * invoke(Parameterized caller, String methodName, Parameterized... arguments)方法调用。 * 经过getThis方法获取this变量 */ runReturn(invoke(getThis(), "toString")); } }); /** * 生成以下方法的字节码: * public static String getDescription(MyObject obj){ * return obj.description(); * } */ creator.createStaticMethod("getDescription", new AClass[]{creator.getCurrentClass()}, new String[]{"obj"}, AClass.STRING_ACLASS, null, Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, new StaticMethodBody(){ @Override public void generateBody(LocalVariable... argus) { /** * 和上面。 * 这里argus[0]就是咱们定义的参数obj。若是须要传递参数能够直接在 * 方法调用的时候添加须要传递的参数,由于这是个变元方法 */ runReturn(invoke(argus[0], "description")); } }); /** * public static void main(String[] args){ * MyObject obj = new MyObject(); * System.out.println("Call static method : " + MyObject.getDescription(obj)); * } */ creator.createStaticMethod("main", new AClass[]{AClassFactory.getProductClass(String[].class)}, new String[]{"args"}, null, null, Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, new StaticMethodBody(){ @Override public void generateBody(LocalVariable... argus) { /** * 首先调用构造方法生成MethodInvokeOperatorGenerateExample obj = new MethodInvokeOperatorGenerateExample(); * 经过invokeConstructor方法实现调用构造方法 * 这个方法后两个参数。 * 1.表示须要构造的类,这里咱们经过调用getMethodOwner获取当前操做类 * 2.表示构造方法的参数。这个参数是个变元参数 */ LocalVariable obj = createVariable("obj", getMethodOwner(), false, invokeConstructor(getMethodOwner())); /** * 实现System.out.println("Call static method : " + MyObject.getDescription(obj)); * 这里将学习到如何生成调用静态方法 * * 调用静态方法是经过invokeStatic(AClass owner, String methodName, Parameterized... arguments) * 实现的。 * 这个方法有三个参数 * 1.经过那个Class调用静态方法。 * 2.静态方法的名称 * 3.参数 */ MethodInvoker getDescriptionInvoker = invokeStatic(getMethodOwner(), "getDescription", obj); invoke(systemOut, "println", append(Value.value("Call static method : "), getDescriptionInvoker)); runReturn(); } }); generate(creator); }
} </pre></div> 更多教程