I have a method fetchObjects(String) that is expected to return an array of Contract business objects. The className parameter tells me what kind of business objects I should return (of course this doesn't make sense in this construed case because I already said I will return Contracts, but it's basically the situation I have in my real scenario). So I get the set of entries from somewhere and load the class of the collection's entries (the type of which is specified by className).
Now I need to construct the array to return, so I use Set's toArray(T[]) method. Using reflection, I build myself an empty Contracts array. But, this gives me a value of static type Object! So next I need to cast it to the appropriate type, which in this case is Contract[] (see "asterisk-underlined" part in the listing below).
My question is: Is there a way, and how, to cast to Contract[] as I do in the listing, but determining the type of the array elements (Contract) only through className (or entriesType)? In other words, what I'd like to do is basically casting like this: (entriesType[]) valueWithStaticTypeObject, where entriesType be replaced by the class specified through the classname parameter, i.e. Contract.
Is this somehow inherently impossible, or can it be done somehow? Maybe using generics?
package xx.testcode;
import java.util.HashSet;
import java.util.Set;
class TypedArrayReflection {
public static void main(String[] args) {
try {
Contract[] contracts = fetchObjects("Contract");
System.out.println(contracts.length);
} catch (ClassNotFoundException e) {}
}
static Contract[] fetchObjects(String className) throws ClassNotFoundException {
Class<?> entriesType = Class.forName("xx.testcode."+className);
Set<?> entries = ObjectManager.getEntrySet(className);
return entries.toArray(
(Contract[]) java.lang.reflect.Array.newInstance(
/********/ entriesType, entries.size()) );
}
}
class Contract { } // business object
class ObjectManager {
static Set<?> getEntrySet(String className) {
if (className.equals("Contract"))
return new HashSet<Contract>();
return null; // Error
}
}
Thanks.
Update: Using the type-safe method
toArray, taken from CodeIdol, I updated my fetchObjects method thus:
static Contract[] fetchObjects(String className) throws ClassNotFoundException {
Class<?> entriesType = Class.forName("xx.testcode."+className);
Set<?> entries = ObjectManager.getEntrySet(className);
return toArray(entries, entriesType); // compile error
// -> "method not applicable for (Set<capture#3-of ?>, Class<capture#4-of ?>)"
}
public static <T> T[] toArray(Collection<T> c, Class<T> k) {
T[] a = (T[]) java.lang.reflect.Array.newInstance(k, c.size());
int i = 0;
for (T x : c)
a[i++] = x;
return a;
}
What do I need to do to get rid of the compiler error quoted in the comment? Do I absolutely have to specify Set<Contract> in the return type of my getEntrySet method so that this can work? Thanks for any pointers.