<p>在任何语言里,数组都是基本的数据类型,咱们这一节将讲述如何生成数组操做。</p> <p>数组操做包括如下几个:</p> <ol> <li>建立数组 </li> <li>获取数组长度 </li> <li>获取数组每一个元素的内容 </li> <li>为数组元素赋值 </li> </ol> <p>咱们接下来对每种操做进行详解。</p> <h3><font style="font-weight: bold">建立数组</font></h3> <hr /> <p>咱们知道在java中建立数有如下几种方式:</p> <ol> <li>只为数组的分配必定大小的空间,好比:int[][] i1 = new int[2][2]; </li> <li>若是是多维数组只为部分维度分配空间,好比:int[][] i2 = new int[2][]; </li> <li>在建立数组的时候为每一个元素赋值,好比:String[] s1 = { "array \"s1\" first value", "array \"s1\" second value" }; </li> <li>这种方式和第三中方式差很少,只不过这里建立的是多维数组,好比:String[][] s2 = { { "s2[0][0]", "s2[0][1]" }, { "s2[1][0]", "s2[1][1]" } }; </li> </ol> <p>那么我么如何使用ASMSupport建立上面的四种数组呢,咱们按照上面介绍的四种方式的顺序来介绍。</p> <h4><font style="font-weight: bold">1.只为数组的分配必定大小的空间,建立int[][] i1 = new int[2][2];</font></h4> <p>这种方式建立数组咱们须要使用的是以下方法:</p> <p><font color="#f79646"><strong>jw.asmsupport.block.ProgramBlock.newArray(final ArrayClass aClass, final Parameterized... allocateDims):</strong></font></p> <ul> <li><strong>参数:</strong> </li> </ul> <ol> <li>当前须要建立的数组值是什么类型(类型是ArrayClass) </li> <li>为其每个维分配的空间数, 这是个变元参数,为何变元参数,在咱们用第二种方式建立数组的时候将会用到。 </li> </ol> <ul> <li><strong>返回类型:</strong> </li> </ul> <p>这个方法返回的是一个<font color="#f79646">jw.asmsupport.operators.array.ArrayValue</font>类型,这个类型就是表示一个数组。咱们看到第一个参数是<font color="#f79646">jw.asmsupport.clazz.ArrayClass</font>类型的, 咱们经过AClassFactory的getArrayClass方法获取其对应的AClass.这里介绍下getArrayClass的方法:</p> <p>getArrayClass有三个重载的方法:</p> <ol> <li><strong>getArrayClass(Class<?> arrayCls):</strong> 这里的参数类型是一个Array的类型。好比咱们须要获取一个int[]类型的ArrayClass,那么咱们能够经过getArrayClass(int[].class)获取 </li> <li><strong>getArrayClass(Class<?> cls, int dim):</strong> 这里的第一参数是一个任意类型的Class。第二个参数表示须要建立的ArrayClass的维数。经过这个方法获得的将是一个以第一个参数为基本类型,维数为第二个参数的ArrayClass。好比:getArrayClass(int.class, 2)将获得一个int[][]类型的ArrayClass;getArrayClass(int[].class, 2)将获得一个int[][][]类型的ArrayClass。 </li> <li><strong>getArrayClass(AClass cls, int dim):</strong> 这个方法和上面那个方法相似,只是将第一个个参数类型变成了AClass。其余相同这里还能够经过getProductClass(Class<?> cls)方法获取ArrayClass,和 getArrayClass(Class<?> arrayCls)用法相同。只是返回类型是AClass。咱们能够将其强制转换成ArrayClass。 </li> </ol> <p>介绍了这么多,那么咱们就能够用下面的代码来生成字节码内容:</p> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:205f032f-17f0-4789-b7cb-f32d502257b3" 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: 945px; height: 50px;" style=" width: 945px; height: 50px;overflow: auto;">ArrayValue av = newArray(AClassFactory.getArrayClass(int[][].class), Value.value(2), Value.value(2)); LocalVariable i1 = createArrayVariable("i1", AClassFactory.getArrayClass(int[][].class), false, av);</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>java
<p> </p>web
<p>解释下上面的代码,首先经过newArray方法建立一个数组值av,再建立一个i1变量并将av赋值给i1再建立System.out.println(ArrayUtils.toString(i1)),下面是对应的生成的代码:</p>apache
<p> </p>编程
<p><font style="font-weight: bold">2.若是是多维数组只为部分维度分配空间,建立int[][] i2 = new int[2][];</font></p>数组
<p>这里咱们用的方法和上面第一种方式的同样,惟一不一样的就是咱们的变元参数的传递,这里咱们只须要传递第一个维度的值就能够了,这也就是为何须要用变元参数的缘由。代码以下:</p>app
<div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:cb7ef075-df46-4f98-80be-1105831260a9" 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: 945px; height: 41px;" style=" width: 945px; height: 41px;overflow: auto;">av = newArray(AClassFactory.getArrayClass(int[][].class), Value.value(2)); LocalVariable i2 = createArrayVariable("i2", AClassFactory.getArrayClass(int[][].class), false, av);</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>ide
<p><strong>3.在建立数组的时候为每一个元素赋值,建立String[] s1 = { "array \"s1\" first value", "array \"s1\" second value" };</strong></p>code
<p>这里有五个方法能够实现这种方式:</p>orm
<ol> <li><strong>public ArrayValue newArrayWithValue(final ArrayClass aClass, final Object arrayObject)</strong> </li>对象
<li><strong>public ArrayValue newArrayWithValue(final ArrayClass aClass, final Parameterized[] values)</strong> </li>
<li><strong>public ArrayValue newArrayWithValue(final ArrayClass aClass, final Parameterized[][] values)</strong> </li>
<li><strong>public ArrayValue newArrayWithValue(final ArrayClass aClass, final Parameterized[][][] values)</strong> </li>
<li><strong>public ArrayValue newArrayWithValue(final ArrayClass aClass, final Parameterized[][][][] values)</strong> </li> </ol>
<p>第2,3,4,5方法其实是经过调用第一方法实现的,因此这里咱们重点讨论第一个方法。这些方法都是有两个参数:</p>
<ol> <li>第一个参数是数组类型和newArray操做是同样的。 </li>
<li>第二个参数是咱们设置的默认值,虽然咱们定义的是个Object类型的,可是在实际应用的时候必须得是Parameterized的数组类型不然会抛异常。至因而几维数组,则根据咱们所定义的类型而定。其实asmsupport始终保持着相似于java的编程方式。好比咱们建立一个二维数组那么咱们能够说设置这个值为:new Parameterized[]{new Parameterized[]{p1, p2}}。 </li> </ol>
<p>咱们能够经过下面的代码实现:</p>
<div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:4cfdeea5-5b01-4435-ade4-1ea85998cf42" 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: 902px; height: 93px;" style=" width: 902px; height: 93px;overflow: auto;">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);</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>
<p><strong>4.建立多维数组的时候同时赋值,建立String[][] s2 = { { "s2[0][0]", "s2[0][1]" }, { "s2[1][0]", "s2[1][1]" } }</strong></p>
<p>这里其实用的也是第三种方式的asmsupport的方法,只不过这个时候咱们须要传入一个二维数组: </p>
<div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:6aa10c73-22e7-4e8b-bcea-9c4c7f6496e9" 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: 1007px; height: 161px;" style=" width: 1007px; height: 161px;overflow: auto;">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);</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>
<p>这里就是建立数组的部分。</p>
<h3><font style="font-weight: bold">获取数组的长度</font></h3>
<hr />
<p>获取数组长度采用的方法是<strong>jw.asmsupport.block.ProgramBlock</strong>的:</p>
<p> <strong><font color="#f79646">public final ArrayLength arrayLength(IVariable arrayReference, Parameterized... dims):</font></strong></p>
<ul> <li><strong><font color="#000000">参数</font></strong> </li> </ul>
<ol> <li>数组对象 </li>
<li>数组的每一个维度的下标,好比咱们要获取i[0][1].length, 咱们就调用arrayLength(a, Value.value(0), Value.value(1)) </li> </ol>
<ul> <li><strong>返回类型</strong> </li> </ul>
<p>返回类型是<strong>jw.asmsupport.operators.array.ArrayLength</strong>,他是asmsupport对获取length操做的抽象.</p>
<h3><font style="font-weight: bold">获取数组每一个元素的内容 </font></h3>
<hr />
<p>获取每一个元素采用的方法是<strong>jw.asmsupport.block.ProgramBlock</strong>的:</p>
<p><strong><font color="#f79646">public final ArrayLoader arrayLoad(IVariable arrayReference, Parameterized pardim, Parameterized... parDims):</font></strong></p>
<ul> <li><strong><font color="#000000">参数</font></strong> </li> </ul>
<ol> <li>数组对象 </li>
<li>第一维的数组的下标 </li>
<li>第二维开始,每一个维度的下标 </li> </ol>
<ul> <li><strong>返回类型</strong> </li> </ul>
<p>返回类型是<strong>jw.asmsupport.operators.array.ArrayLoader</strong>,他是asmsupport对获取获取数组元素操做的抽象.</p>
<h3><font style="font-weight: bold">为数组元素赋值</font></h3>
<hr />
<p>为数组元素赋值采用的方法是<strong>jw.asmsupport.block.ProgramBlock</strong>的:</p>
<p><strong><font color="#f79646">public final ArrayStorer arrayStore(IVariable arrayReference, Parameterized value, Parameterized dim, Parameterized... dims):</font></strong></p>
<ul> <li><strong><font color="#000000">参数</font></strong> </li> </ul>
<ol> <li>数组对象 </li>
<li>为数组元素赋予的值 </li>
<li>第一维的数组的下标 </li>
<li>第二维开始,每一个维度的下标 </li> </ol>
<ul> <li><strong>返回类型</strong> </li> </ul>
<p>返回类型是<strong>jw.asmsupport.operators.array.ArrayStorer</strong>,他是asmsupport对获取获取数组元素操做的抽象.</p>
<h3><font style="font-weight: bold">实例</font></h3>
<hr />
<p>咱们须要生成以下代码:</p>
<div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:1675aea4-a49c-4bfb-be4e-a86977fcab5b" 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: 474px;" style=" width: 796px; height: 474px;overflow: auto;">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));
}</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>
<p>对应的asmsupport的代码以下:</p>
<div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:d69c19ba-b885-42ad-9dad-3f98f02f0731" 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: 2224px;" style=" width: 796px; height: 2224px;overflow: auto;">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;
/**
*/ 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); }
} </pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>