<h2>ASMSupport教程4.5 在Class中生成算术运算符</h2> <p>这节我们开始介绍ASMSupport如何生成算数运算符(+-*/%),依旧先看我们需要生成的java代码:</p> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:22b13b06-a0d6-4b8e-b7cd-7680d4653dde" 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: 439px; height: 1027px;" style=" width: 439px; height: 1027px;overflow: auto;">package generated.operators;
import java.io.PrintStream; import java.util.Random;
public class ArithmeticOperatorGenerateExample { static void printInt(String s, int i) { System.out.println(s + " = " + i); }
static void printFloat(String s, float f) { System.out.println(s + " = " + f); }
public static void main(String[] args) { Random rand = new Random(); int j = rand.nextInt(100) + 1; int k = rand.nextInt(100) + 1; printInt("j", j); printInt("k", k); int i = j + k; printInt("j + k", i); i = j - k; printInt("j - k", i); i = k / j; printInt("k / j", i); i = k * j; printInt("k * j", i); i = k % j; printInt("k % j", i); j %= k; printInt("j %= k", j); float v = rand.nextFloat(); float w = rand.nextFloat(); printFloat("v", v); printFloat("w", w); float u = v + w; printFloat("v + w", u); u = v - w; printFloat("v - w", u); u = v * w; printFloat("v * w", u); u = v / w; printFloat("v / w", u); u += v; printFloat("u += v", u); u -= v; printFloat("u -= v", u); u *= v; printFloat("u *= v", u); u /= v; printFloat("u /= v", u); } }</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>
<p>对应的代码如下,由于代码比较多,我们将对应的java代码写在asmsupport代码之上,便于对比。</p>
<div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:1bfe82d6-deba-48f1-853a-a748666c5148" 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: 462px; height: 3000px;" style=" width: 462px; height: 3000px;overflow: auto;">package example.operators;
import java.util.Random;
import org.objectweb.asm.Opcodes;
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 jw.asmsupport.operators.numerical.arithmetic.Addition;
import example.AbstractExample;
public class ArithmeticOperatorGenerate extends AbstractExample {
/**
* @param args
*/
public static void main(String[] args) {
ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "generated.operators.ArithmeticOperatorGenerateExample", null, null);
//printIn方法
creator.createStaticMethod("printInt", new AClass[]{AClass.STRING_ACLASS, AClass.INT_ACLASS}, new String[]{"s", "i"}, null, null, 0, new StaticMethodBody(){
@Override
public void generateBody(LocalVariable... argus) {
invoke(systemOut, "println", append(argus[0], Value.value(" = "), argus[1]));
runReturn();
}
});
//printIn方法
creator.createStaticMethod("printFloat", new AClass[]{AClass.STRING_ACLASS, AClass.FLOAT_ACLASS}, new String[]{"s", "f"}, null, null, 0, new StaticMethodBody(){
@Override
public void generateBody(LocalVariable... argus) {
invoke(systemOut, "println", append(argus[0], Value.value(" = "), argus[1]));
runReturn();
}
});
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) {
//Random rand = new Random();
LocalVariable rand = createVariable("rand", AClassFactory.getProductClass(Random.class), false, invokeConstructor(AClassFactory.getProductClass(Random.class)));
//rand.nextInt(100) + 1
Addition add1 = add(invoke(rand, "nextInt", Value.value(100)), Value.value(1));
//int j = rand.nextInt(100) + 1;
LocalVariable j = createVariable("j", AClass.INT_ACLASS, false, add1);
//int k = rand.nextInt(100) + 1;
LocalVariable k = createVariable("k", AClass.INT_ACLASS, false, add1);
//printInt("j", j);
invokeStatic(getMethodOwner(), "printInt", Value.value("j"), j);
//printInt("k", k);
invokeStatic(getMethodOwner(), "printInt", Value.value("k"), k);
//j + k
Addition add2 = add(j, k);
//int i = j + k;
LocalVariable i = createVariable("i", AClass.INT_ACLASS, false, add2);
//printInt("j + k", i);
invokeStatic(getMethodOwner(), "printInt", Value.value("j + k"), i);
//i = j - k;
assign(i, sub(j, k));
//printInt("j - k", i);
invokeStatic(getMethodOwner(), "printInt", Value.value("j - k"), i);
//i = k / j;
assign(i, div(k, j));
//printInt("k / j", i);
invokeStatic(getMethodOwner(), "printInt", Value.value("k / j"), i);
//i = k * j;
assign(i, mul(k, j));
//printInt("k * j", i);
invokeStatic(getMethodOwner(), "printInt", Value.value("k * j"), i);
//i = k % j;
assign(i, mod(k, j));
//printInt("k % j", i);
invokeStatic(getMethodOwner(), "printInt", Value.value("k % j"), i);
//j %= k;
assign(j, mod(j, k));
//printInt("j %= k", j);
invokeStatic(getMethodOwner(), "printInt", Value.value("j %= k"), j);
//rand.nextFloat()
MethodInvoker nextFloat = invoke(rand, "nextFloat");
//v = rand.nextFloat();
LocalVariable v = createVariable("v", AClass.FLOAT_ACLASS, false, nextFloat);
//w = rand.nextFloat();
LocalVariable w = createVariable("w", AClass.FLOAT_ACLASS, false, nextFloat);
//printFloat("v", v);
invokeStatic(getMethodOwner(), "printFloat", Value.value("v"), v);
//printFloat("w", w);
invokeStatic(getMethodOwner(), "printFloat", Value.value("w"), w);
//u = v + w;
LocalVariable u = createVariable("u", AClass.FLOAT_ACLASS, false, add(v,w));
//printFloat("v + w", u);
invokeStatic(getMethodOwner(), "printFloat", Value.value("v + w"), u);
//u = v - w;
assign(u, sub(v, w));
//printFloat("v - w", u);
invokeStatic(getMethodOwner(), "printFloat", Value.value("v - w"), u);
//u = v * w;
assign(u, mul(v, w));
//printFloat("v * w", u);
invokeStatic(getMethodOwner(), "printFloat", Value.value("v * w"), u);
//u = v / w;
assign(u, div(v, w));
//printFloat("v / w", u);
invokeStatic(getMethodOwner(), "printFloat", Value.value("v / w"), u);
//u += v;
assign(u, add(u, v));
//printFloat("u += v", u);
invokeStatic(getMethodOwner(), "printFloat", Value.value("u += v"), u);
//u -= v;
assign(u, sub(u, v));
//printFloat("u -= v", u);
invokeStatic(getMethodOwner(), "printFloat", Value.value("u -= v"), u);
//u *= v;
assign(u, mul(u, v));
//printFloat("u *= v", u);
invokeStatic(getMethodOwner(), "printFloat", Value.value("u *= v"), u);
//u /= v;
assign(u, div(u, v));
//printFloat("u /= v", u);
invokeStatic(getMethodOwner(), "printFloat", Value.value("u /= v"), u);
runReturn();
}
});
generate(creator);
}
} </pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>
<p>这里我们不逐行解释,只对生成算术操作的方法进行解释:</p>
<ul> <li><strong>jw.asmsupport.block.ProgramBlock.add(Parameterized factor1, Parameterized factor2) :</strong> 生成加法操作,生成的代码是factor1+factor2,返回类型<strong><font color="#ffc000">jw.asmsupport.operators.numerical.arithmetic.Addition</font></strong> </li>
<li><strong>jw.asmsupport.block.ProgramBlock.sub(Parameterized factor1, Parameterized factor2) :</strong> 生成减法操作,生成的代码是factor1-factor2 , 返回类型<strong><font color="#ffc000">jw.asmsupport.operators.numerical.arithmetic.Subtraction</font></strong> </li>
<li><strong>jw.asmsupport.block.ProgramBlock.mul(Parameterized factor1, Parameterized factor2):</strong> 生成乘法操作,生成的代码是factor1*factor2 , 返回类型<strong><font color="#ffc000">jw.asmsupport.operators.numerical.arithmetic.Multiplication</font></strong> </li>
<li><strong>jw.asmsupport.block.ProgramBlock.div(Parameterized factor1, Parameterized factor2):</strong>  生成除法操作,生成的代码是factor1/factor2 , 返回类型<strong><font color="#ffc000">jw.asmsupport.operators.numerical.arithmetic.Division</font></strong> </li>
<li><strong>jw.asmsupport.block.ProgramBlock.mod(Parameterized factor1, Parameterized factor2):</strong>生成取模操作,生成的代码是factor1%factor2 , 返回类型<strong><font color="#ffc000">jw.asmsupport.operators.numerical.arithmetic.Modulus</font></strong> </li> </ul>
<p>这些方法的返回值都是继承自jw.asmsupport.Parameterized接口的,这个接口意味着这个类还可以被其他的操作所使用,这个很容易理解,我可以将a+b这个运算作为参数传入某个方法,比如有个方法是c(int a),我们可以这样调用:c(a+b)。 </p>