ASMSupport教程4.11 生成数组操作

<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 = { &quot;array \&quot;s1\&quot; first value&quot;, &quot;array \&quot;s1\&quot; second value&quot; }; </li> <li>这种方式和第三中方式差不多,只不过这里创建的是多维数组,比如:String[][] s2 = { { &quot;s2[0][0]&quot;, &quot;s2[0][1]&quot; }, { &quot;s2[1][0]&quot;, &quot;s2[1][1]&quot; } }; </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&lt;?&gt; arrayCls):</strong> 这里的参数类型是一个Array的类型。比如我们需要获取一个int[]类型的ArrayClass,那么我们可以通过getArrayClass(int[].class)获取 </li> <li><strong>getArrayClass(Class&lt;?&gt; 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&lt;?&gt; cls)方法获取ArrayClass,和 getArrayClass(Class&lt;?&gt; 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(&quot;i1&quot;, AClassFactory.getArrayClass(int[][].class), false, av);</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>

<p>&#160;</p>

<p>解释下上面的代码,首先通过newArray方法创建一个数组值av,再创建一个i1变量并将av赋值给i1再创建System.out.println(ArrayUtils.toString(i1)),下面是对应的生成的代码:</p>

<p>&#160;</p>

<p><font style="font-weight: bold">2.如果是多维数组只为部分维度分配空间,创建int[][] i2 = new int[2][];</font></p>

<p>这里我们用的方法和上面第一种方式的一样,唯一不同的就是我们的变元参数的传递,这里我们只需要传递第一个维度的值就可以了,这也就是为什么需要用变元参数的原因。代码如下:</p>

<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(&quot;i2&quot;, AClassFactory.getArrayClass(int[][].class), false, av);</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>

<p><strong>3.在创建数组的时候为每个元素赋值,创建String[] s1 = { &quot;array \&quot;s1\&quot; first value&quot;, &quot;array \&quot;s1\&quot; second value&quot; };</strong></p>

<p>这里有五个方法可以实现这种方式:</p>

<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(&quot;array \&quot;s1\&quot; first value&quot;), Value.value(&quot;array \&quot;s1\&quot; second value&quot;)}); LocalVariable s1 = createArrayVariable(&quot;s1&quot;, 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 = { { &quot;s2[0][0]&quot;, &quot;s2[0][1]&quot; }, { &quot;s2[1][0]&quot;, &quot;s2[1][1]&quot; } }</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(&quot;s2[0][0]&quot;); Value s201 = Value.value(&quot;s2[0][1]&quot;); Value s210 = Value.value(&quot;s2[1][0]&quot;); Value s211 = Value.value(&quot;s2[1][1]&quot;);

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>&#160;<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(&quot;i1 = &quot; + ArrayUtils.toString(i1));

int[][] i2 = new int[2][];
System.out.println(&quot;i2 = &quot; + ArrayUtils.toString(i2));

String[] s1 = { &quot;array \&quot;s1\&quot; first value&quot;, &quot;array \&quot;s1\&quot; second value&quot; };
System.out.println(&quot;s1 = &quot; + ArrayUtils.toString(s1));

String[][] s2 = { { &quot;s2[0][0]&quot;, &quot;s2[0][1]&quot; }, { &quot;s2[1][0]&quot;, &quot;s2[1][1]&quot; } };
System.out.println(&quot;s2 = &quot; + ArrayUtils.toString(s2));

//获取数组长度操作
System.out.println(&quot;length of s2 is &quot; + s2.length);
System.out.println(&quot;length of s2[0] is &quot; + s2[0].length);

//获取数组内容的操作
System.out.println(&quot;value of s2[0] is &quot; + ArrayUtils.toString(s2[0]));
System.out.println(&quot;value of s2[0][0] is &quot; + ArrayUtils.toString(s2[0][0]));

//为数组内容赋值的操作
s2[0] = new String[]{ &quot;new s2[0][0]&quot;, &quot;new s2[0][1]&quot; };
s2[1][0] = &quot;new s2[1][0]&quot;;
System.out.println(&quot;new value of s2 is : &quot; + 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;

/**

  • 在这个例子中我们将实现数组的相关操作
  • @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 , &quot;generated.operators.ArrayOperatorGenerateExample&quot;, null, null);
	
	creator.createStaticMethod(&quot;main&quot;, new AClass[]{AClassFactory.getProductClass(String[].class)}, new String[]{&quot;args&quot;}, 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(&quot;i1 = &quot; + ArrayUtils.toString(i1));
			 */
			ArrayValue av = newArray(AClassFactory.getArrayClass(int[][].class), Value.value(2), Value.value(2));
			LocalVariable i1 = createArrayVariable(&quot;i1&quot;, AClassFactory.getArrayClass(int[][].class), false, av);
			invoke(systemOut, &quot;println&quot;, append(Value.value(&quot;i1 = &quot;), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), &quot;toString&quot;, i1)));
			
			/*
			 * 下面一段代码将生成如下代码:
			 * int[][] i2 = new int[2][];
	         * System.out.println(&quot;i2 = &quot; + ArrayUtils.toString(i2));
			 */
			av = newArray(AClassFactory.getArrayClass(int[][].class), Value.value(2));
			LocalVariable i2 = createArrayVariable(&quot;i2&quot;, AClassFactory.getArrayClass(int[][].class), false, av);
			invoke(systemOut, &quot;println&quot;, append(Value.value(&quot;i2 = &quot;), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), &quot;toString&quot;, i2)));
			
			/*
			 * 对应如下代码:
			 * String[] s1 = new String[]{&quot;array \&quot;s1\&quot; first value&quot;, &quot;array \&quot;s1\&quot; second value&quot;};
			 * System.out.println(&quot;s1 = &quot; + ArrayUtils.toString(s1));
			 */
			av = newArrayWithValue(AClassFactory.getArrayClass(String[].class), new Value[]{Value.value(&quot;array \&quot;s1\&quot; first value&quot;), Value.value(&quot;array \&quot;s1\&quot; second value&quot;)});
			LocalVariable s1 = createArrayVariable(&quot;s1&quot;, AClassFactory.getArrayClass(String[].class), false, av);
			invoke(systemOut, &quot;println&quot;, append(Value.value(&quot;s1 = &quot;), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), &quot;toString&quot;, s1)));

			/*
			 * 对应如下代码:
			 * String[][] s2 = {{&quot;s2[0][0]&quot;, &quot;s2[0][1]&quot;},{&quot;s2[1][0]&quot;, &quot;s2[1][1]&quot;}};
	         * System.out.println(&quot;s2 = &quot; + ArrayUtils.toString(s2));
			 */
			Value s200 = Value.value(&quot;s2[0][0]&quot;);
			Value s201 = Value.value(&quot;s2[0][1]&quot;);
			Value s210 = Value.value(&quot;s2[1][0]&quot;);
			Value s211 = Value.value(&quot;s2[1][1]&quot;);
			
			av = newArrayWithValue(AClassFactory.getArrayClass(String[][].class), 
					new Value[][]{new Value[]{s200, s201}, new Value[]{s210, s211}});
			LocalVariable s2 = createArrayVariable(&quot;s2&quot;, AClassFactory.getArrayClass(String[][].class), false, av);
			invoke(systemOut, &quot;println&quot;, append(Value.value(&quot;s2 = &quot;), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), &quot;toString&quot;, s2)));

			/*
			 * 接下来我们将获取数组的长度:
			 * 代码如下:
			 * System.out.println(&quot;length of s2 is &quot; + s2.length);
			 * System.out.println(&quot;length of s2[0] is &quot; + s2[0].length);
			 */
			invoke(systemOut, &quot;println&quot;, append(Value.value(&quot;length of s2 is &quot;), arrayLength(s2)));
			invoke(systemOut, &quot;println&quot;, append(Value.value(&quot;length of s2[0] is &quot;), arrayLength(s2, Value.value(0))));

			/*
			 * 接下来我们将实现如何获取数组的值
			 * 代码如下:
			 * System.out.println(&quot;value of s2[0] is &quot; + ArrayUtils.toString(s2[0]));
			 * System.out.println(&quot;value of s2[0][0] is &quot; + s2[0][0]);
			 */
			//s2[0]
			Parameterized arrayLoader = arrayLoad(s2, Value.value(0));
			invoke(systemOut, &quot;println&quot;, append(Value.value(&quot;value of s2[0] is &quot;), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), &quot;toString&quot;, arrayLoader)));
			
			//s2[0][0]
			arrayLoader = arrayLoad(s2, Value.value(0), Value.value(0));
			invoke(systemOut, &quot;println&quot;, append(Value.value(&quot;value of s2[0][0] is &quot;), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), &quot;toString&quot;, arrayLoader)));
			
			/*
			 * 接下来是如何实现为数组单元赋值的操作
			 * 代码如下
			 * s2[0] = new String[]{&quot;new s2[0][0]&quot;, &quot;new s2[0][1]&quot;};
			 * s2[1][0] = &quot;new s2[1][0]&quot;
			 * System.out.println(&quot;new value of s2 is : &quot; + ArrayUtils.toString(s2));
			 */
			arrayStore(s2, newArrayWithValue(AClassFactory.getArrayClass(String[].class), new Parameterized[]{Value.value(&quot;new s2[0][0]&quot;), Value.value(&quot;new s2[0][1]&quot;)}), Value.value(0));
			arrayStore(s2, Value.value(&quot;new s2[1][0]&quot;), Value.value(1), Value.value(0));
			invoke(systemOut, &quot;println&quot;, append(Value.value(&quot;new value of s2 is : &quot;), invokeStatic(AClassFactory.getProductClass(ArrayUtils.class), &quot;toString&quot;, s2)));
			
			runReturn();
		}
    });
	generate(creator);
}

} </pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>

转载于:https://my.oschina.net/wensiqun/blog/143277

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值