У меня есть метод fetchObjects(String)
, который должен вернуть массив Contract
бизнес-объектов. Параметр className
говорит мне, какие бизнес-объекты мне следует возвращать (конечно, в данном случае это не имеет смысла, потому что я уже сказал, что верну Contract
s, но в основном это ситуация, с которой я столкнулся в моем реальном сценарий). Поэтому я откуда-то получаю набор записей и загружаю класс записей коллекции (тип которых указан className
).
Теперь мне нужно создать массив для возврата, поэтому я использую метод Set
toArray(T[])
. Используя рефлексию, я создаю пустой массив Contracts. Но, это дает мне значение статического типа Object
! Итак, затем мне нужно привести его к соответствующему типу, который в данном случае равен Contract[]
(см. Часть с подчеркиванием звездочкой в листинге ниже).
У меня вопрос: есть ли способ и как привести к Contract[]
, как я делаю в листинге, , но определить тип элементов массива (Contract
) только через className
(или entriesType
)? Другими словами, то, что я хотел бы сделать, это в основном приведение типа: (entriesType[]) valueWithStaticTypeObject
, где recordsType должен быть заменен на класс, указанный в параметре classname
, т.е. Contract
.
Это как-то по своей сути невозможно, или это можно сделать как-то? Может быть, с использованием дженериков?
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
}
}
Спасибо.
Обновление: Используя типобезопасный метод
toArray
, взятый из
CodeIdol , я обновил свой
fetchObjects
метод таким образом:
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;
}
Что мне нужно сделать, чтобы избавиться от ошибки компилятора, указанной в комментарии? Обязательно ли указывать Set<Contract>
в типе возврата моего getEntrySet
метода, чтобы это могло работать? Спасибо за любые указатели.