【问题标题】:What is the purpose of java.lang.reflect.Array's getter and setter methods?java.lang.reflect.Array 的 getter 和 setter 方法的目的是什么?
【发布时间】:2010-05-27 19:48:44
【问题描述】:

Java 类java.lang.reflect.Array 提供了一组用于动态创建数组的工具。然而,除此之外,它还有一整套用于访问(获取、设置和长度)数组的方法。我不明白这一点,因为您可以(并且可能会)在创建时将动态生成的数组转换为数组,这意味着您可以使用正常的数组访问(括号符号)功能。其实看源码就知道,就是类所做的一切,对数组进行转换,如果转换失败则抛出异常。

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

更新

所有基本的get*()set*() 方法似乎尤其无用,因为您需要事先知道数组的类型才能知道使用哪种方法。

更新 2

谢谢大家,您的意见很有教育意义!除了newInstance()(可能还有getLength())之外,我真的看不到什么时候会使用这个类,但我现在意识到这些其他方法仍然非常有用。 p>

【问题讨论】:

  • "get() 方法返回一个对象..." - 你可以用一个对象做很多事情...

标签: java arrays reflection


【解决方案1】:

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

所有数组都没有数组超类,因此无论类型如何,都没有统一的访问元素或数组大小的方法。 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 Harmony。那里的实现不遵守 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() 相同 - 提供(松散的)类型 -不可知的数组访问。

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

【讨论】:

  • 我不明白你的意思,标准括号表示法在所有类型中都是统一的,包括原语。由于您注意到它返回一个对象,因此您最终仍然需要进行强制转换 - 对象或数组。因此,您为什么不直接转换数组?
  • 有些用例你不关心类型。你不需要投射。例如,计算数组中的重复值。我已经用代码示例更新了我的答案。
  • 不过,原始的 get/set 方法似乎毫无用处,不是吗?
  • 哇,不知怎的,我从来没有意识到 docjar 不是 Sun 实现的!
  • 感谢您帮助我了解它的用处。
【解决方案2】:

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

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

【讨论】:

  • 您能举个例子吗?我下载了 commons-beanutils 的源代码并查找了 Array 类的引用,但没有看到任何。
  • java.lang.reflect.Array 的 grep 应该返回一些结果。查看org.apache.commons.beanutils 包中的BeanUtilsBeanPropertyUtilsBean
  • 嘿,我猜Windows“全文搜索”根本不是很全文。谢谢。
  • 呵呵,这也是我的发现。我刚刚找到了一个MS knowledge base article,它似乎可以解释这种行为(至少对于 XP):简而言之,Windows 文件搜索“太聪明了”,无法执行全文搜索。
【解决方案3】:

关于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...() 方法允许您不必静态知道原始数组的类型。

【讨论】:

  • 字节[] b = 新字节[1];短 [] s = 新短 [1]; int[] i = 新的 int[1];长[] l = 新长[1]; b[0] = (字节)1; s[0] = (字节)1; i[0] = (字节)1; l[0] = (字节)1;效果一样好...
  • 呃,搞砸了我的新台词。
  • @dimo414:你错过了所有这一切。除非它是一个数组,否则您不能使用 [] 运算符。除非您知道原始类型,否则当它是原始数组时,您不能强制转换为数组。因此,如果您正在编写一个应该接受 byte[]short[]long[]int[] 的库函数并将第一个元素设置为 5,则必须执行四次 instanceof 检查以确定类型,然后将其转换为相应的原始数组,然后进行赋值。 Array.setByte(someArrayRef, 0, (byte)5) 和单线做同样的事情。
  • 我明白了。我想我一直在努力思考/为什么/你会遇到这种情况,但现在它更有意义了。
猜你喜欢
  • 2011-02-07
  • 2014-12-20
  • 1970-01-01
  • 2017-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多