JAVA - использование класса, полученного по его имени (строковое значение)
это то, что мой код выглядит, если я использую предопределенный класс:
List<MyClass> result = new ArrayList<MyClass>();
try {
Query query = mgr.newQuery(MyClass.class);
for(Object obj : (List<Object>) query.execute()) {
result.add(((MyClass) obj));
}
}
....
return result;
теперь мне нужно быть более общим: начиная с общего имени класса (в виде строки, то есть "TheChosenOne" ) мне нужно сделать то же самое, но я не могу понять, как выполнить роль роли..
Просто чтобы сделать пример того, что я пытаюсь сделать:
String str = "TheChosenOne"; //this value may change
Class cls;
List<Object> result = new ArrayList<Object>();
try {
if(str.equals("TheChosenOne"))
cls = Class.forName("com.blabla.TheChosenOne");
else if(str.equals("Rabbit"))
cls = Class.forName("com.blabla.Rabbit");
else if(str.equals("Batman"))
cls = Class.forName("com.heroes.Batman");
else
cls = null;
if(cls != null){
Query query = mgr.newQuery(MyClass.class);
for(Object obj : (List<Object>) query.execute()) {
result.add(((???) obj)); //I need help here!
}
}
}
...
return result;
Я взял "Class.forname()..." часть здесь.
Любые предложения? Спасибо заранее, наилучшие пожелания
Ответы
Ответ 1
То, что вы пытаетесь сделать, не нужно, потому что ваш список объявлен как List<Object>
, поэтому приведение не требуется.
- Перед редактированием -
Не уверен, что я понимаю, что вам нужно, но вы пытались использовать:
Class.cast(object)
Это метод java.lang.Class
Ответ 2
Я думаю, что то, что вы пытаетесь сделать, может быть достигнуто с помощью генериков.
Например, такой метод:
public <E> List<E> getList(Class<E> clazz) {
List<E> result = new ArrayList<E>();
if(clazz != null){
Query query = mgr.newQuery(MyClass.class);
for(E obj : (List<E>)query.execute()) {
result.add(obj);
}
}
return result;
}
Можно вызвать с помощью:
getList(TheChosenOne.class)
И он вернет объект List<TheChosenOne>
Ответ 3
Если result
- это List<Object>
, вам вообще не нужен бросок, просто add(obj)
будет работать нормально.
Если вам нужна безопасность типа времени компиляции, вам придется передать объект Class
, а не строку, содержащую его имя, и использовать подпись общего метода
public <T> List<T> doQuery(Class<T> theClass) {
List<T> result = new ArrayList<T>();
try {
Query query = mgr.newQuery(theClass);
for(T obj : (List<T>) query.execute()) {
result.add(obj);
}
}
....
return result;
}
Если вы пройдете этот маршрут и имеете возможность модифицировать класс Query
, тогда вы можете захотеть сделать этот параметр параметрированным
public class Query<E> {
public List<E> execute() { ... }
}
// and in mgr
public <T> Query<T> newQuery(Class<T> cls)
который затем позволит вам сказать
Query<T> query = mgr.newQuery(theClass);
for(T obj : query.execute()) {
result.add(obj);
без литья вообще.
Ответ 4
Я считаю, что cls.cast(obj)
- это то, что вы ищете.
Ответ 5
Я думаю, вам нужно сделать это следующим образом: используя оператор instance of
, чтобы проверить тип класса, а затем выполните листинг типов
for(Object obj : (List<Object>) query.execute()) {
if(obj instance of Batman)
result.add(((Batman) obj));
else if(obj instance of Cat)
result.add(((Cat) obj));
// and so on
...
...
}
Ответ 6
Вам не нужно бросать, помещая объект в ArrayList,
result.add(obj);
Если вы хотите, чтобы вы могли использовать его при получении из списка
cls .cast(result.get(1));