2016-10-20 6 views
0

Пожалуйста, посмотрите на следующий код:JAVA ошибки несоответствия типов при использовании Class.forName на дженерики

Class<? extends List> class1; 
Class<? extends List<?>> class2; 
Class<? extends List<? extends Object>> class3; 
class1 = class2.asSubclass(List.class);  // 1. OK 
class1 = class3.asSubclass(List.class);  // 2. OK 
class2 = class1.asSubclass(List.class);  // 3. Error Type Mismatch 
class2 = class3.asSubclass(List.class);  // 4. Error Type Mismatch 
class3 = class1.asSubclass(List.class);  // 5. Error Type Mismatch 
class3 = class2.asSubclass(List.class);  // 6. Error Type Mismatch 
String className; 
class1 = Class.forName(className);   // 7. Error Type Mismatch 
class2 = Class.forName(className);   // 8. Error Type Mismatch 
class3 = Class.forName(className);   // 9. Error Type Mismatch 
class1 = Class.forName(className).asSubclass(List.class); // 10. OK 
class2 = Class.forName(className).asSubclass(List.class); // 11. Error Type Mismatch 
class3 = Class.forName(className).asSubclass(List.class); // 12. Error Type Mismatch 

1., 2. и 10. в порядке, и мне нравится 10. В частности, из-за его чистота, но мне не нравится использовать RAW-тип, поэтому я пошел на подстановочный знак.

К сожалению, все остальные потерпели неудачу из-за ошибки несоответствия типа, если я не делаю листинг плюс @SuppressWarnings("unchecked") комбо.

Это случай, когда нужно использовать тип RAW, чтобы избежать литья и @SuppressWarnings("unchecked")?

В противном случае, как вам исправить 11. и 12.? (забудьте о 3. к 9., они просто здесь для демонстрации разных комбинаций, мой код их не использует)

+0

'className' - пустая строка. 'static Class \t forName (String className)' Возвращает объект Class, связанный с классом или интерфейсом с заданным именем строки. Что вы ожидаете, когда будете передавать неконкретизированную переменную? – kpie

+0

Это не проблема. Я могу изменить приведенное выше значение 'String className =" a.b.c ";' все еще те же ошибки, что и ошибки Compile time, а не ошибки времени выполнения. – user1589188

+0

- переменная a.b.c во время выполнения? – kpie

ответ

2

К сожалению, это фундаментальное ограничение языка из-за аспектов стирания типа. Class Объекты, представляющие не сырые общие типы, не существуют и не могут быть получены или созданы. Следующие выражения все производят тот же объект, даже при сравнении по ==:

new ArrayList<Integer>().getClass(); 
new ArrayList<String>().getClass(); 
Class.forName("java.util.ArrayList"); 
ArrayList.class; 

И это бросает ClassNotFoundException:

Class.forName("java.util.ArrayList<Integer>"); 

Так что да, вы должны использовать необработанный тип.

+0

Большое спасибо. Не могли бы вы также прокомментировать использование wildcard + cast + '@SuppressWarnings (" unchecked ")'? – user1589188

+0

@ user1589188 Этот подход технически обоснован, но либо не был бы полезен, либо устранял бы непроверенные предупреждения из других мест, где используется искусственно заброшенный объект, что потенциально может привести к небезопасным следам, которые не замечаются. – Douglas