ASMSupport教程4.11 生成数组操作

Stella981
• 阅读 704

在任何语言里,数组都是基本的数据类型,我们这一节将讲述如何生成数组操作。

数组操作包括以下几个:

  1. 创建数组
  2. 获取数组长度
  3. 获取数组每个元素的内容
  4. 为数组元素赋值

我们接下来对每种操作进行详解。

创建数组


我们知道在java中创建数有以下几种方式:

  1. 只为数组的分配一定大小的空间,比如:int\[\]\[\] i1 = new int\[2\]\[2\];
  2. 如果是多维数组只为部分维度分配空间,比如:int\[\]\[\] i2 = new int\[2\]\[\];
  3. 在创建数组的时候为每个元素赋值,比如:String\[\] s1 = { "array \\"s1\\" first value", "array \\"s1\\" second value" };
  4. 这种方式和第三中方式差不多,只不过这里创建的是多维数组,比如:String\[\]\[\] s2 = { { "s2\[0\]\[0\]", "s2\[0\]\[1\]" }, { "s2\[1\]\[0\]", "s2\[1\]\[1\]" } };

那么我么如何使用ASMSupport创建上面的四种数组呢,我们按照上面介绍的四种方式的顺序来介绍。

1.只为数组的分配一定大小的空间,创建int\[\]\[\] i1 = new int\[2\]\[2\];

这种方式创建数组我们需要使用的是如下方法:

jw.asmsupport.block.ProgramBlock.newArray(final ArrayClass aClass, final Parameterized... allocateDims):

  • 参数:
  1. 当前需要创建的数组值是什么类型(类型是ArrayClass)
  2. 为其每一个维分配的空间数, 这是个变元参数,为什么变元参数,在我们用第二种方式创建数组的时候将会用到。
  • 返回类型:

这个方法返回的是一个jw.asmsupport.operators.array.ArrayValue类型,这个类型就是表示一个数组。我们看到第一个参数是jw.asmsupport.clazz.ArrayClass类型的, 我们通过AClassFactory的getArrayClass方法获取其对应的AClass.这里介绍下getArrayClass的方法:

getArrayClass有三个重载的方法:

  1. getArrayClass(Class<?> arrayCls): 这里的参数类型是一个Array的类型。比如我们需要获取一个int\[\]类型的ArrayClass,那么我们可以通过getArrayClass(int\[\].class)获取
  2. getArrayClass(Class<?> cls, int dim): 这里的第一参数是一个任意类型的Class。第二个参数表示需要创建的ArrayClass的维数。通过这个方法得到的将是一个以第一个参数为基本类型,维数为第二个参数的ArrayClass。比如:getArrayClass(int.class, 2)将得到一个int\[\]\[\]类型的ArrayClass;getArrayClass(int\[\].class, 2)将得到一个int\[\]\[\]\[\]类型的ArrayClass。
  3. getArrayClass(AClass cls, int dim): 这个方法和上面那个方法类似,只是将第一个个参数类型变成了AClass。其他相同这里还可以通过getProductClass(Class<?> cls)方法获取ArrayClass,和 getArrayClass(Class<?> arrayCls)用法相同。只是返回类型是AClass。我们可以将其强制转换成ArrayClass。

介绍了这么多,那么我们就可以用下面的代码来生成字节码内容:

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" };

这里有五个方法可以实现这种方式:

  1. public ArrayValue newArrayWithValue(final ArrayClass aClass, final Object arrayObject)
  2. public ArrayValue newArrayWithValue(final ArrayClass aClass, final Parameterized\[\] values)
  3. public ArrayValue newArrayWithValue(final ArrayClass aClass, final Parameterized\[\]\[\] values)
  4. public ArrayValue newArrayWithValue(final ArrayClass aClass, final Parameterized\[\]\[\]\[\] values)
  5. public ArrayValue newArrayWithValue(final ArrayClass aClass, final Parameterized\[\]\[\]\[\]\[\] values)

第2,3,4,5方法实际上是通过调用第一方法实现的,所以这里我们重点讨论第一个方法。这些方法都是有两个参数:

  1. 第一个参数是数组类型和newArray操作是一样的。
  2. 第二个参数是我们设置的默认值,虽然我们定义的是个Object类型的,但是在实际应用的时候必须得是Parameterized的数组类型否则会抛异常。至于是几维数组,则根据我们所定义的类型而定。其实asmsupport始终保持着类似于java的编程方式。比如我们创建一个二维数组那么我们可以说设置这个值为:new Parameterized\[\]{new Parameterized\[\]{p1, p2}}。

我们可以通过下面的代码实现:

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):

  • 参数
  1. 数组对象
  2. 数组的每个维度的下标,比如我们要获取i\[0\]\[1\].length, 我们就调用arrayLength(a, Value.value(0), Value.value(1))
  • 返回类型

返回类型是jw.asmsupport.operators.array.ArrayLength,他是asmsupport对获取length操作的抽象.

获取数组每个元素的内容


获取每个元素采用的方法是jw.asmsupport.block.ProgramBlock的:

public final ArrayLoader arrayLoad(IVariable arrayReference, Parameterized pardim, Parameterized... parDims):

  • 参数
  1. 数组对象
  2. 第一维的数组的下标
  3. 第二维开始,每个维度的下标
  • 返回类型

返回类型是jw.asmsupport.operators.array.ArrayLoader,他是asmsupport对获取获取数组元素操作的抽象.

为数组元素赋值


为数组元素赋值采用的方法是jw.asmsupport.block.ProgramBlock的:

public final ArrayStorer arrayStore(IVariable arrayReference, Parameterized value, Parameterized dim, Parameterized... dims):

  • 参数
  1. 数组对象
  2. 为数组元素赋予的值
  3. 第一维的数组的下标
  4. 第二维开始,每个维度的下标
  • 返回类型

返回类型是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(&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));

}

对应的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 , &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);
}

}

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
Java开发者容易犯的十个错误
!(https://oscimg.oschina.net/oscnet/c9f00cc918684fbe8a865119d104090b.gif)Top1.数组转换为数组列表将数组转换为数组列表,开发者经常会这样做:\java\List<StringlistArrays.asList(arr);Arr
Stella981 Stella981
3年前
ASMSupport教程4.8 生成逻辑运算操作
<p在java中有以下逻辑运算符:</p<ul<li&amp;&amp;:条件与</li<li||:条件或</li<li&amp;:布尔型的逻辑与</li<li|:布尔型的逻辑或</li<li^:布尔型的逻辑异或</li<li!:非操作</li</ul<p那么接下来我们将些段例子
Wesley13 Wesley13
3年前
mysql 5.7 windows zip安装
<ol<limysql官网下载windowszip安装包并解压(D:wampmysql56winx64)</li<li添加pathD:wampmysql5722winx64bin</li<li创建data目录D:\\wamp\\mysql56winx64\\data</li<li<p创建mysql配置文
Stella981 Stella981
3年前
ASMSupport教程4.12 生成方法调用操作
<p这一节我们讲如何用ASMSupport生成方法调用的操作,方法调用包括下面四种类型:</p<ol<li调用构造方法<li调用静态方法<li调用非静态方法<li调用当前类的方法<li调用父类方法</li</ol<p首先我们需要看我们想要生成的类:</p<p代码1:</p<h3<divid"scid:9D
Wesley13 Wesley13
3年前
HTML快捷写法大全
父子用\ \Ulli\3\<ul\    <li\</li\    <li\</li\    <li\</li\</ul\兄弟之间用,也可以省写\pspan\,\ul\<p\</p\<span
达里尔 达里尔
11个月前
给数组添加新数据,判断数据是否重复
多选要进行数组拼接,希望判断往原数组里添的新数据是否重复,封装个简易方法languageconstdataArrayname:'aaa',id:1,name:'bbb',id:2;constnewDataname:'ccc',id:2;//要添加的新数