Как создать литерал класса известного типа: Class>
принять следующие:
public Class<List<String>> getObjectType() {
// what can I return here?
}
какое литеральное выражение класса я могу вернуть из этого метода, которое удовлетворит обобщениям и компиляции? List.class
не будет компилироваться, и не будет List.<String>class
.
Если вам интересно "почему", я пишу реализацию Spring's FactoryBean<List<String>>
, что требует от меня реализации Class<List<String>> getObjectType()
. Однако, это не весенний вопрос.
edit: мои жалобные крики были услышаны полномочия, которые находятся в SpringSource, и поэтому Spring 3.0.1 будет иметь тип возврата getObjectType()
изменено на Class<?>
, который аккуратно избегает проблемы.
10 ответов
вы всегда можете отдать то, что вам нужно, как это
return (Class<List<String>>) new ArrayList<String>().getClass();
или
return (Class<List<String>>) Collections.<String>emptyList().getClass();
но я предполагаю, что это не то, что вам нужно. Ну, это работает, с предупреждением, но это не совсем "красиво".
Я только что нашел это
почему нет литерала класса для подстановочных параметризованных типов?
поскольку параметризованный тип подстановочного знака не имеет точного представления типа времени выполнения.
Так что кастинг может это единственный путь.
вы никогда не должны использовать конструкцию Class<List<String>>
. Это бессмысленно, и должно произвести предупреждение на Java (но не делает). Экземпляры класса всегда представляют необработанные типы, поэтому вы можете иметь Class<List>
, вот и все. Если вы хотите, чтобы что-то представляло собой овеществленный универсальный тип, например List<String>
, вам нужен "маркер супер типа", как Guice использует:
http://google-guice.googlecode.com/git/javadoc/com/google/inject/TypeLiteral.html
существование Class<List<String>>
по своей сути опасно. вот почему:
// This statement generates a warning - for a reason...
Class<List<String>> unsafeListClass = (Class<List<String>>) (Class<?>) List.class;
List<Integer> integerList = new ArrayList<Integer>(); // Ok
integerList.add(42); // Ok
System.out.println(unsafeListClass.isInstance(integerList)); // Prints "true".
List<String> stringList =
unsafeListClass.cast(integerList); // Succeeds, with no warning!
stringList.add("Hello, World!"); // Also succeeds with no warning
for (int x: integerList) {
// Compiles without warning, but throws ClassCastException at runtime
System.out.println(100-x);
}
нашел этой ссылке on springframework.org что дает некоторое представление.
Э. Г.
List<String> myList = new ArrayList<String>();
return (Class<List<String>>)myList.getClass();
вы можете реализовать этот метод следующим образом:
public Class<List<String>> getObjectType() {
return (Class<List<String>>) ((Class)List.class);
}
проверьте это обсуждение на форумах SUN:
http://forums.sun.com/thread.jspa?threadID=5253007
и ссылка на сообщение в блоге, которое описывает работу с помощью "токенов супер типа":
Я не уверен, что это вообще возможно, так как любой литерал класса будет скомпилирован в Class.forName(...)
и поскольку это происходит во время выполнения, общей информации не осталось.
Как насчет этого:
public class TestMain {
public static void main(String[] args) throws Exception {
Type type = TestMain.class.getMethod("dummy").getGenericReturnType();
System.out.println("type = " + type);
}
public List<Integer> dummy() {return null;}
}
печатается:
type = java.util.List<java.lang.Integer>
следующий подход проблематичен:
> public Class<List<String>> getModelType() {
> return (Class<List<String>>) new ArrayList<String>().getClass();
> }
например, если вы хотите проверить, говорит ли объект типа
org.eclipse.emf.common.util.BasicEList<String>
типа
List<String>
на основе результата вышеупомянутого подхода getModelType (), например:
BasicEList<String> fromObject = ...;
if (getModelType().isAssignableFrom(fromObject.getClass())) {
transferFromModelToUi(getModelType().cast(fromObject));
}
это приведет к false, тогда как это должно быть true, потому что оба объекта реализуют список интерфейса (так как getModelType () возвращает объект класса списка типов, а не список ArrayList.)
вот подход, который работал для меня (немного громоздкий, но приводит к правильным результатам в приведенном выше примере, может быть перемещен в статический инициализатор):
public Class<List<String>> getModelType() {
Class<?> arrayListClass = new ArrayList<String>().getClass();
Class<?>[] interfaces = arrayListClass.getInterfaces();
int index = 0;
for (int i = 0; i < interfaces.length; i++) {
if (interfaces[i].equals(List.class)) {
index = i;
break;
}
}
return (Class<List<String>>) interfaces[index];
}