在写这一篇文章之前,关于数组的反射的操作有了解多少
思考一下:
如何知道一个对象为一个数组,如何获取数组中的单元的类型
如何操作一个数组,对数组的下标进行反射设值
带着这些问题,文章的讲解方面如下:
鉴别数组类型
用反射创建一个数组
访问和设值数组元素
数组的反射错误用法
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 失去精度的操作将会出错
}
}
网友评论