(8)关于数组反射的基本使用

2018-10-06  本文已影响0人  Mrsunup

在写这一篇文章之前,关于数组的反射的操作有了解多少

思考一下:
如何知道一个对象为一个数组,如何获取数组中的单元的类型
如何操作一个数组,对数组的下标进行反射设值

带着这些问题,文章的讲解方面如下:

鉴别数组类型
用反射创建一个数组
访问和设值数组元素
数组的反射错误用法

1.鉴别数组类型

/**
 * 鉴别数组类型
 *    Class.isArray  可以判断类型是否为数组
 *    class.getComponentType 可以得到一个数组元素类型
 *   对于字段类型为:byte[],type为class [B  ,componmentType组件类型为byte
 *   对于字段类型为:String[][],type为 class [[Ljava.lang.String;   ,componmentType组件类型为一维数组 [Ljava.lang.String;
 */
public class ArrayFind {
    public static void main(String... args) {
        args  =new String []{"java.nio.ByteBuffer"};
        boolean found = false;
        try {
            Class<?> cls = Class.forName(args[0]);
            Field[] flds = cls.getDeclaredFields();
            for (Field f : flds) {
                //得到字段类型
                Class<?> c = f.getType();
                if (c.isArray()) {//判断类型是否是数组
                    found = true;
                    //c.getComponentType() 得到数组单元的类型
                    out.format("%s%n"
                                    + "           Field: %s%n"
                                    + "            Type: %s%n"
                                    + "  Component Type: %s%n",
                            f, f.getName(), c, c.getComponentType());
                }
            }
            if (!found) {
                out.format("No array fields%n");
            }
        } catch (ClassNotFoundException x) {
            x.printStackTrace();
        }
    }
}

输出 结果如下:

final byte[] java.nio.ByteBuffer.hb
           Field: hb
            Type: class [B
  Component Type: byte

2.用反射创建一个数组

下面的例子展示了如何创建一个string数组,并给数组元素设置

/**
 * @Project: jdk
 * @description:  数组的创建,以给数组设置值
 * @author: sunkang
 * @create: 2018-10-06 12:31
 * @ModificationHistory who      when       What
 **/
public class ArrayStringCreator {
    public static void main(String[] args) {
        Class  clazz = String.class;
        //创建一个String 数组,长度为5
        Object arr =  Array.newInstance(clazz,5);
        //给数组指定的小标设置值
        Array.set(arr,0,"1");
        Array.set(arr,1,"2");
        Array.set(arr,2,"3");
        Array.set(arr,3,"4");

        //类型强转为String数组
        String[] oo  = (String[]) arr;
        System.out.println(Arrays.toString(oo));
    }
}

输出结果如下:

[1, 2, 3, 4, null]

3.访问和设值数组元素

下面的例子展示了如何个二维数组的创建与设置值

/**
 * 二维数组的创建与设值
 */
public class CreateMatrix {
    public static void main(String... args) {
        //创建一个二维数组,相当于   new int[2][2];
        Object matrix = Array.newInstance(int.class, 2 ,2);
        //获取二维数组的第一行
        Object row0 = Array.get(matrix, 0);
        Object row1 = Array.get(matrix, 1);
        //二维数组设置值,第一行设置值
        Array.setInt(row0, 0, 1);
        Array.setInt(row0, 1, 2);

        //第二行设置值
        Array.setInt(row1, 0, 3);
        Array.setInt(row1, 1, 4);

        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
                out.format("matrix[%d][%d] = %d%n", i, j, ((int[][])matrix)[i][j]);
    }
}

结果为:

matrix[0][0] = 1
matrix[0][1] = 2
matrix[1][0] = 3
matrix[1][1] = 4

4.数组的反射错误用法

/**
 * 数组类型设置不正确,导致 转换错误
 *原本类型是Integer数组,在发射代码中,类型检查只有在运行期间在会发生,所以无法对原生类型进行包装
 *  art[0] = 1   ,这个是可以的,因为编译器对1进行了包装,使1变成了引用类型
 */
public class ArrayTroubleAgain {
    public static void main(String... args) {
        Integer[] ary = new Integer[2];
        try {
//          Array.setInt(ary, 0, 1);  // IllegalArgumentException  不可以

//          Array.setInt(ary,0,new Integer(1));//不可以


//          Integer.isAssignableFrom().  符合这里对象是可以的
            //这里设置的1 当做是Ojbect对象
            Array.set(ary,0,1);  //可以,set用于引用类型

            Array.set(ary,0,new Integer(1));//可以


        } catch (IllegalArgumentException x) {
            err.format("Unable to box%n");
        } catch (ArrayIndexOutOfBoundsException x) {
            x.printStackTrace();
        }
    }
}
/**
 * 空数组的问题
 */
public class ArrayTrouble {
    public static void main(String... args) {
        Object o = Array.newInstance(int.class, 0);
        int[] i = (int[])o;
        int[] j = new int[0];
        out.format("i.length = %d, j.length = %d, args.length = %d%n",
                   i.length, j.length, args.length);
        Array.getInt(o, 0);  // ArrayIndexOutOfBoundsException
    }
}
/**
 * 
 * 值的精度缩小会出错的
 * 
 *  遵循的返回如下,这里 int数组,设置的元素必须是byte和short和int
 * byte , short, int, long, float, or double
 */
public class ArrayTroubleToo {
    public static void main(String... args) {
        Object o = new int[2];
        Array.setByte(o,0,"2".getBytes()[0]);  //
        Array.setShort(o, 1, (short)2);  // widening, succeeds
//        Array.setLong(o, 1, 2L);         // narrowing, fails   失去精度的操作将会出错
    }
}
上一篇 下一篇

猜你喜欢

热点阅读