What is the purpose of java.lang.reflect.Array's getter and setter methods?
Java Class java.lang.reflect.Array provides a set of tools for creating an array dynamically. However in addition to that it has a whole set of methods for accessing (get, set, and length) an array. I don't understand the point of this, since you can (and presumably would) cast your dynamically generated array as an array upon creation, which means you can use the normal array access (bracket notation) functionality. In fact, looking at the source code you can see that is all开发者_JS百科 the class does, cast the array, and throw an exception if the cast fails.
So what's the point / usefulness of all of these extra methods?
Update
All of the primitive get*()
and set*()
methods seem especially unhelpful, considering you need to know the type of the array beforehand in order to know which method to use.
Update 2
Thanks everyone, your input has been very educational! I can't really see when I'd be using this class for anything other than newInstance()
(and maybe getLength()
), but I now realize these other methods are still quite useful.
This class is quite esoteric - most uses of arrays know the type of the array, so this class is typically most useful when implementing code that handles arrays generically.
There is no array superclass for all arrays, so there is no uniform way of accessing elements or the size of an array regardless of type. The java.lang.reflect.Array
fills this gap and allows you to access the array in the same way regardless from type. For example, to get the value at a given index from any array (returned as an object).
It's parameteric polymorphism. Sure, you could code this yourself if you know the type - you just cast. If you don't know the array type, or it can be several types, you would check the possibilities and cast appropriately - which is what the code in reflect.Array
does.
EDIT: In response to the comment. Consider how you would solve this problem - how to count the number of times a value is duplicated in an array. Without the type-agnostic Array class, this would not be possible to code, without explicitly casting the array, so you would need a different function for each array type. Here, we have one function that handles any type of 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: Regarding the get*() and set*() methods. The source code link above links to Apache harmony. The implementation there does not adhere to the Sun Javadocs. For example, from the getInt method
@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
This implies that the actual array could be byte[]
, short[]
or int[]
. This is not the case with the Harmony implementation, which only takes an int[]
. (Incidentally, the Sun implementation uses native methods for most of the Array class.) The get*() and set*() methods are there for the same reason as get()
, getLength()
- to provide (loosely) type-agnostic array access.
Not exactly something you need to use every day, but I imagine it provides value for those that need it.
These methods relieve you from the burden of checking and casting the array yourself, if all you know is "that object is an array of some (possibly primitive) type".
I myself have seen uses of this only in frameworks and utilities, like commons-beanutils
. This framework reflectively accesses properties of java beans, and uses the Array
methods to access elements of array properties.
Regarding the set...()
methods, they do provide some use:
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);
You don't need to know whether the array you're dealing with is an int[]
or a long[]
to set a value to 5
, for example.
Edit I changed the example to hopefully demonstrate the fact that set...()
methods allow you to not necessarily know the primitive array's type statically.
精彩评论