<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> 更多教程