在任何语言里,数组都是基本的数据类型,我们这一节将讲述如何生成数组操作。
数组操作包括以下几个:
我们接下来对每种操作进行详解。
我们知道在java中创建数有以下几种方式:
那么我么如何使用ASMSupport创建上面的四种数组呢,我们按照上面介绍的四种方式的顺序来介绍。
这种方式创建数组我们需要使用的是如下方法:
jw.asmsupport.block.ProgramBlock.newArray(final ArrayClass aClass, final Parameterized... allocateDims):
这个方法返回的是一个jw.asmsupport.operators.array.ArrayValue类型,这个类型就是表示一个数组。我们看到第一个参数是jw.asmsupport.clazz.ArrayClass类型的, 我们通过AClassFactory的getArrayClass方法获取其对应的AClass.这里介绍下getArrayClass的方法:
getArrayClass有三个重载的方法:
介绍了这么多,那么我们就可以用下面的代码来生成字节码内容:
ArrayValue av = newArray(AClassFactory.getArrayClass(int[][].class), Value.value(2), Value.value(2));LocalVariable i1 = createArrayVariable(“i1”, AClassFactory.getArrayClass(int[][].class), false, av);
解释下上面的代码,首先通过newArray方法创建一个数组值av,再创建一个i1变量并将av赋值给i1再创建System.out.println(ArrayUtils.toString(i1)),下面是对应的生成的代码:
2.如果是多维数组只为部分维度分配空间,创建int[][] i2 = new int[2][];
这里我们用的方法和上面第一种方式的一样,唯一不同的就是我们的变元参数的传递,这里我们只需要传递第一个维度的值就可以了,这也就是为什么需要用变元参数的原因。代码如下:
av = newArray(AClassFactory.getArrayClass(int[][].class), Value.value(2)); LocalVariable i2 = createArrayVariable("i2", AClassFactory.getArrayClass(int[][].class), false, av);
3.在创建数组的时候为每个元素赋值,创建String[] s1 = { "array \"s1\" first value", "array \"s1\" second value" };
这里有五个方法可以实现这种方式:
第2,3,4,5方法实际上是通过调用第一方法实现的,所以这里我们重点讨论第一个方法。这些方法都是有两个参数:
我们可以通过下面的代码实现:
av = newArrayWithValue(AClassFactory.getArrayClass(String[].class), new Value[]{Value.value("array \"s1\" first value"), Value.value("array \"s1\" second value")}); LocalVariable s1 = createArrayVariable("s1", AClassFactory.getArrayClass(String[].class), false, av);
4.创建多维数组的时候同时赋值,创建String[][] s2 = { { "s2[0][0]", "s2[0][1]" }, { "s2[1][0]", "s2[1][1]" } }
这里其实用的也是第三种方式的asmsupport的方法,只不过这个时候我们需要传入一个二维数组:
Value s200 = Value.value("s2[0][0]"); Value s201 = Value.value("s2[0][1]"); Value s210 = Value.value("s2[1][0]"); Value s211 = Value.value("s2[1][1]"); av = newArrayWithValue(AClassFactory.getArrayClass(String[][].class), new Value[][]{new Value[]{s200, s201}, new Value[]{s210, s211}}); LocalVariable s2 = createArrayVariable("s2", AClassFactory.getArrayClass(String[][].class), false, av);
这里就是创建数组的部分。
获取数组长度采用的方法是jw.asmsupport.block.ProgramBlock的:
public final ArrayLength arrayLength(IVariable arrayReference, Parameterized... dims):
返回类型是jw.asmsupport.operators.array.ArrayLength,他是asmsupport对获取length操作的抽象.
获取每个元素采用的方法是jw.asmsupport.block.ProgramBlock的:
public final ArrayLoader arrayLoad(IVariable arrayReference, Parameterized pardim, Parameterized... parDims):
返回类型是jw.asmsupport.operators.array.ArrayLoader,他是asmsupport对获取获取数组元素操作的抽象.
为数组元素赋值采用的方法是jw.asmsupport.block.ProgramBlock的:
public final ArrayStorer arrayStore(IVariable arrayReference, Parameterized value, Parameterized dim, Parameterized... dims):
返回类型是jw.asmsupport.operators.array.ArrayStorer,他是asmsupport对获取获取数组元素操作的抽象.
我们需要生成如下代码:
public static void willGenerate(){ int[][] i1 = new int[2][2]; System.out.println("i1 = " + ArrayUtils.toString(i1)); int[][] i2 = new int[2][]; System.out.println("i2 = " + ArrayUtils.toString(i2)); String[] s1 = { "array \"s1\" first value", "array \"s1\" second value" }; System.out.println("s1 = " + ArrayUtils.toString(s1)); String[][] s2 = { { "s2[0][0]", "s2[0][1]" }, { "s2[1][0]", "s2[1][1]" } }; System.out.println("s2 = " + ArrayUtils.toString(s2)); //获取数组长度操作 System.out.println("length of s2 is " + s2.length); System.out.println("length of s2[0] is " + s2[0].length); //获取数组内容的操作 System.out.println("value of s2[0] is " + ArrayUtils.toString(s2[0])); System.out.println("value of s2[0][0] is " + ArrayUtils.toString(s2[0][0])); //为数组内容赋值的操作 s2[0] = new String[]{ "new s2[0][0]", "new s2[0][1]" }; s2[1][0] = "new s2[1][0]"; System.out.println("new value of s2 is : " + ArrayUtils.toString(s2)); }
对应的asmsupport的代码如下:
package example.operators; import org.apache.commons.lang.ArrayUtils; import org.objectweb.asm.Opcodes; import jw.asmsupport.Parameterized; 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.array.ArrayValue; import example.AbstractExample; /** * 在这个例子中我们将实现数组的相关操作 * * @author 温斯群(Joe Wen) * */ public class ArrayOperatorGenerate extends AbstractExample { /** * @param args */ public static void main(String[] args) { ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC , "generated.operators.ArrayOperatorGenerateExample", null, null); 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) { /* * 1.首先我们需要创建一个数组。我们有两只方式创建数组,第一种是在创建数组的时候 * 为其分配数组空间。第二种是创建数组的时候为其分配初试值 */ //int[][] i1 = new int[1][2]; //System.out.println(ArrayUtils.toString(i1)); /* * * 对应如下代码: * int[][] i1 = new int[1][2]; * System.out.println("i1 = " + ArrayUtils.toString(i1)); */ ArrayValue av = newArray(AClassFactory.getArrayClass(int[][].class), Value.value(2), Value.value(2)); LocalVariable i1 = createArrayVariable("i1", AClassFactory.getArrayClass(int[][].class), false, av); invoke(systemOut, "println", append(Value.value("i1 = "), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), "toString", i1))); /* * 下面一段代码将生成如下代码: * int[][] i2 = new int[2][]; * System.out.println("i2 = " + ArrayUtils.toString(i2)); */ av = newArray(AClassFactory.getArrayClass(int[][].class), Value.value(2)); LocalVariable i2 = createArrayVariable("i2", AClassFactory.getArrayClass(int[][].class), false, av); invoke(systemOut, "println", append(Value.value("i2 = "), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), "toString", i2))); /* * 对应如下代码: * String[] s1 = new String[]{"array \"s1\" first value", "array \"s1\" second value"}; * System.out.println("s1 = " + ArrayUtils.toString(s1)); */ av = newArrayWithValue(AClassFactory.getArrayClass(String[].class), new Value[]{Value.value("array \"s1\" first value"), Value.value("array \"s1\" second value")}); LocalVariable s1 = createArrayVariable("s1", AClassFactory.getArrayClass(String[].class), false, av); invoke(systemOut, "println", append(Value.value("s1 = "), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), "toString", s1))); /* * 对应如下代码: * String[][] s2 = {{"s2[0][0]", "s2[0][1]"},{"s2[1][0]", "s2[1][1]"}}; * System.out.println("s2 = " + ArrayUtils.toString(s2)); */ Value s200 = Value.value("s2[0][0]"); Value s201 = Value.value("s2[0][1]"); Value s210 = Value.value("s2[1][0]"); Value s211 = Value.value("s2[1][1]"); av = newArrayWithValue(AClassFactory.getArrayClass(String[][].class), new Value[][]{new Value[]{s200, s201}, new Value[]{s210, s211}}); LocalVariable s2 = createArrayVariable("s2", AClassFactory.getArrayClass(String[][].class), false, av); invoke(systemOut, "println", append(Value.value("s2 = "), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), "toString", s2))); /* * 接下来我们将获取数组的长度: * 代码如下: * System.out.println("length of s2 is " + s2.length); * System.out.println("length of s2[0] is " + s2[0].length); */ invoke(systemOut, "println", append(Value.value("length of s2 is "), arrayLength(s2))); invoke(systemOut, "println", append(Value.value("length of s2[0] is "), arrayLength(s2, Value.value(0)))); /* * 接下来我们将实现如何获取数组的值 * 代码如下: * System.out.println("value of s2[0] is " + ArrayUtils.toString(s2[0])); * System.out.println("value of s2[0][0] is " + s2[0][0]); */ //s2[0] Parameterized arrayLoader = arrayLoad(s2, Value.value(0)); invoke(systemOut, "println", append(Value.value("value of s2[0] is "), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), "toString", arrayLoader))); //s2[0][0] arrayLoader = arrayLoad(s2, Value.value(0), Value.value(0)); invoke(systemOut, "println", append(Value.value("value of s2[0][0] is "), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), "toString", arrayLoader))); /* * 接下来是如何实现为数组单元赋值的操作 * 代码如下 * s2[0] = new String[]{"new s2[0][0]", "new s2[0][1]"}; * s2[1][0] = "new s2[1][0]" * System.out.println("new value of s2 is : " + ArrayUtils.toString(s2)); */ arrayStore(s2, newArrayWithValue(AClassFactory.getArrayClass(String[].class), new Parameterized[]{Value.value("new s2[0][0]"), Value.value("new s2[0][1]")}), Value.value(0)); arrayStore(s2, Value.value("new s2[1][0]"), Value.value(1), Value.value(0)); invoke(systemOut, "println", append(Value.value("new value of s2 is : "), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), "toString", s2))); runReturn(); } }); generate(creator); } }