java.lang.reflect.Array的getter和setter方法的目的是什么?

时间:2010-05-27 19:48:45

标签: java arrays reflection

Java Class java.lang.reflect.Array提供了一组用于动态创建数组的工具。然而,除此之外,它还有一整套用于访问(获取,设置和长度)数组的方法。我不明白这一点,因为您可以(并且可能会)在创建时将动态生成的数组转换为数组,这意味着您可以使用常规数组访问(括号表示法)功能。实际上,查看源代码,您可以看到这是所有类所做的,转换数组,并在转换失败时抛出异常。

那么所有这些额外方法的重点/用处是什么?

更新

所有原始get*()set*()方法似乎尤其无用,考虑到您需要预先知道数组的类型以便知道使用哪种方法。

更新2

谢谢大家,您的意见非常有教育意义!我无法真正看到何时将此类用于newInstance()以外的任何事情(也许getLength()),但我现在意识到这些其他方法仍然相当是有用的。

3 个答案:

答案 0 :(得分:8)

这个类非常深奥 - 大多数数组的使用都知道数组的类型,所以在实现一般处理数组的代码时,这个类通常最有用。

所有数组都没有数组超类,因此无论类型如何,都没有统一的方法来访问元素或数组的大小。 java.lang.reflect.Array填补了这个空白,允许您以相同的方式访问数组,无论类型如何。例如,从任何数组获取给定索引处的值(作为对象返回)。

这是parameteric polymorphism。当然,你可以自己编码,如果你知道类型 - 你只是演员。如果您不知道数组类型,或者它可以是几种类型,您可以检查可能性并进行适当的转换 - 这是reflect.Array中的代码所做的。

编辑:回应评论。考虑如何解决此问题 - 如何计算值在数组中重复的次数。如果没有类型无关的Array类,如果没有显式地转换数组,就不可能进行编码,因此每个数组类型都需要不同的函数。在这里,我们有一个函数可以处理任何类型的数组。

public Map<Object, Integer> countDuplicates(Object anArray)
{
    if (!anArray.getClass().isArray())
        throw new IllegalArgumentException("anArray is not an array");

    Map<Object,Integer> dedup = new HashMap<Object,Integer>();
    int length = Array.getLength(anArray);
    for (int i=0; i<length; i++)
    {
        Object value = Array.get(anArray, i);         
        Integer count = dedup.get(value);
        dedup.put(value, count==null ? 1 : count+1);
    }
    return dedup;
}

EDIT2:关于get *()和set *()方法。上面的源代码链接链接到Apache和声。那里的实现不遵守Sun Javadocs。例如,来自getInt方法

@throws IllegalArgumentException If the specified object is not an array, 
or if the indexed element cannot be converted to the return type 
by an identity or widening conversion 

这意味着实际数组可以是byte[]short[]int[]。 Harmony实现不是这种情况,只需要int[]。 (顺便提一下,Sun实现对大多数Array类使用本机方法。)get *()和set *()方法的出现与get()getLength()相同 - 提供(松散地)类型不可知的数组访问。

并不是每天都需要使用的东西,但我认为它为那些需要它的人提供了价值。

答案 1 :(得分:2)

如果您知道“该对象是某种(可能是原始的)类型的数组”,这些方法可以减轻您自己检查和转换数组的负担。

我自己只在框架和实用程序中看到过这种情况,例如commons-beanutils。该框架反射访问java bean的属性,并使用Array方法访问数组属性的元素。

答案 2 :(得分:2)

关于set...()方法,它们提供了一些用途:

Object a = new byte[1], b = new short[1], c = new int[1], d = new long[1];
Array.setByte(a, 0, (byte)1);
Array.setByte(b, 0, (byte)1);
Array.setByte(c, 0, (byte)1);
Array.setByte(d, 0, (byte)1);

例如,您无需知道要处理的数组是int[]还是long[]来将值设置为5

编辑我更改了示例以希望证明set...()方法允许您不必静态地知道原始数组的类型。