`

java数组反射

 
阅读更多

数组反射

如果因为某种原因,您并不确定参数或对象是不是数组,您可以检索对象的 Class 对象并询问它。 Class 类的 isArray() 方法将会告诉您。一旦您知道拥有了一个数组,您可以询问 Class 的 getComponentType() 方法,您实际拥有的是什么类型的数组。如果 isArray() 方法返回 false,那么 getComponentType() 方法返回空。否则返回元素的 Class 类型。如果数组是多维的,您可以递归调用 isArray() 。它将仍只包含一个 component 类型。此外,您可以用在 java.lang.reflect 包里找到的 Array 类的 getLength() 方法获取数组的长度。

为了演示,清单 2-3 显示了传递给 main() 方法的参数是 java.lang.String 对象的数组,其中数组长度由命令行参数的个数确定:


清单 2-3. 使用反射检查数组类型和长度

 

public class ArrayReflection {
  public static void main (String args[]) {
    printType(args);
  }
  private static void printType (Object object) {
    Class type = object.getClass();
    if (type.isArray()) {
      Class elementType = type.getComponentType();
      System.out.println("Array of: " + elementType);
      System.out.println(" Length: " + Array.getLength(object));
    }
  }
}
 

注意:如果 printType() 用于前面定义的 buttons 和 components 变量调用,每个都会表明数组是 java.awt.Button 类型。

如果不使用 isArray() 和 getComponentType() 方法,而且试图打印数组的 Class 类型,您将获得一个包含 [ ,后面跟着一个字母和类名(如果是个基本数据类型就没有类名)的字符串。例如,如果您试图打印出上述 printType() 方法中的类型变量,您将获得 class [Ljava.lang.String; 作为输出。

除了询问一个对象是不是数组以及是什么类型的数组之外,您还可以在运行时用 java.lang.reflect.Array class 创建数组。这对于创建一般实用例程非常有用,这些例程执行数组任务,比如将大小加倍。(我们会立即回到那一点。)

要创建一个新数组,使用 Array 的 newInstance() 方法,它有两种变化形式。对于一维数组您通常将使用较简单版本,它的执行方式如语句 new type [length] 所示,并作为对象返回数组: public static Object newInstance(Class type, int length) 。例如,下面的代码创建一个五个整数空间大小的数组:

int array[] = (int[])Array.newInstance(int.class, 5);
 

注意:要为基本数据类型指定 Class 对象,只要在基本数据类型名末尾添加 .class 就可以了。您还可以使用包装类中的 TYPE 变量,如 Integer.TYPE。

newInstance() 方法中的第二种变化形式要求维数被指定为整型数组: public static Object newInstance(Class type,int dimensions []) 。在创建一个一维数组的最简单的情况下,您将创建只有一个元素的数组。换句话说,如果您要创建包含五个整数的相同数组,您需要创建一个单个元素 5 的数组并传递到 newInstance() 方法,而不是传递整数值 5。

int dimensions[] = {5};
int array[] = (int[])Array.newInstance(int.class, dimensions);

 在您只需要创建一个矩形数组的时候,您就可以将每个数组长度填充到这个 dimensions 数组中。例如,下面的代码与创建一个 3 X 4 的整数数组等价。

int dimensions[] = {3, 4};
int array[][] = (int[][])Array.newInstance(int.class, dimensions);

 但是,如果您需要创建一个非矩形数组,您将需要多次调用 newInstance() 方法。第一次调用将定义外部数组的长度,并获得一个看上去很古怪的类参数([].class 适用于元素为 float 类型的数组)。每个后续调用将定义每个内部数组的长度。例如,下面演示了如何创建一个元素为 float 类型的数组,其内部数组的大小设置像一组保龄球瓶:第一排一个元素,第二排两个,第三排三个,第四排四个。为了帮您将这种情况形象化,让我们回顾早先在图 2-4 展示的三角形数组。

float bowling[][] = (float[][])Array.newInstance(float[].class, 4);
for (int i=0; i<4; i++) {
  bowling[i] = (float[])Array.newInstance(float.class, i+1);
}
 

一旦在运行时创建了数组,您还可以获取和设置数组元素。不过通常不会这样做,除非键盘上的方括号键失灵或者您在动态的编程环境(程序被创建时数组名 未知)中工作。 如表 2-2 所示, Array 类有一系列的 getter 和 setter 方法用来获取和设置数组元素。使用什么方法取决于您处理的数组类型。

表 2-2. 数组 getter 和 setter 方法

Getter 方法  Setter 方法 

get(Object array, int index) set(Object array, int index, Object value)
getBoolean(Object array, int index) setBoolean(Object array, int index, boolean value)
getByte(Object array, int index) setByte(Object array, int index, byte value)
getChar(Object array, int index) setChar(Object array, int index, char value)
getDouble(Object array, int index) setDouble(Object array, int index, double value)
getFloat(Object array, int index) setFloat(Object array, int index, float value)
getInt(Object array, int index) setInt(Object array, int index, int value)
getLong(Object array, int index) setLong(Object array, int index, long value)
getShort(Object array, int index) setShort(Object array, int index, short value) 

 注意:您可以一直使用 get() 和 set() 方法。如果数组是一个基本数据类型数组, get() 方法的返回值或 set() 方法的值参数将被包装到用于基本数据类型的包装类中,像装着一个 int 数组的 Integer 类那样。

清单 2-4 提供了一个如何创建、填充以及显示数组信息的完整示例。方括号只在 main() 方法的声明中使用。


清单 2-4. 使用反射创建、填充和显示数组

import java.lang.reflect.Array;
import java.util.Random;
public class ArrayCreate {
  public static void main (String args[]) {
    Object array = Array.newInstance(int.class, 3);
    printType(array);
    fillArray(array);
    displayArray(array);
  }
  private static void printType (Object object) {
    Class type = object.getClass();
    if (type.isArray()) {
      Class elementType = type.getComponentType();
      System.out.println("Array of: " + elementType);
      System.out.println("Array size: " + Array.getLength(object));
    }
  }
  private static void fillArray(Object array) {
    int length = Array.getLength(array);
    Random generator = new Random(System.currentTimeMillis());
    for (int i=0; i<length; i++) {
      int random = generator.nextInt();
      Array.setInt(array, i, random);
    }
  }
  private static void displayArray(Object array) {
    int length = Array.getLength(array);
    for (int i=0; i<length; i++) {
      int value = Array.getInt(array, i);
      System.out.println("Position: " + i +", value: " + value);
    }
  }
}

 运行时,输出将如下所示(尽管随机数会不同):

Array of: int
Array size: 3
Position: 0, value: -54541791
Position: 1, value: -972349058
Position: 2, value: 1224789416
 

让我们返回到早先的,创建一个将数组大小加倍的方法的示例。既然您知道如何获取数组的类型,您可以创建一种方法用来将任意类型数组的大小加倍。这个方法确保我们能在获取它的长度和类型之前得到数组。然后在复制原来的那组元素之前,它将新数组的大小加倍。

 

static Object doubleArray(Object original) {
  Object returnValue = null;
  Class type = original.getClass();
  if (type.isArray()) {
    int length = Array.getLength(original);
    Class elementType = type.getComponentType();
    returnValue = Array.newInstance(elementType, length*2);
    System.arraycopy(original, 0, returnValue, 0, length);
  }
  return returnValue;
}
 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics