Class <T>и статический метод Class.forName () сводят меня с ума - PullRequest
10 голосов
/ 23 мая 2010

этот код не компилируется.Мне интересно, что я делаю неправильно:

private static Importable getRightInstance(String s) throws Exception {
 Class<Importable> c = Class.forName(s);
 Importable i = c.newInstance();
 return i;
}

, где Importable - это интерфейс, а строка s - это имя реализующего класса.Компилятор говорит:

./Importer.java:33: incompatible types
found   : java.lang.Class<capture#964 of ?>
required: java.lang.Class<Importable>
  Class<Importable> c = Class.forName(format(s));

спасибо за любую помощь!

Все решения

Class<? extends Importable> c = Class.forName(s).asSubclass(Importable.class);

и

Class<? extends Importable> c = (Class<? extends Importable>) Class.forName(s);

и

Class<?> c = Class.forName(format(s));
Importable i = (Importable)c.newInstance();

выдает эту ошибку (которую я не понимаю):

Exception in thread "main" java.lang.IncompatibleClassChangeError: class C1 
has interface Importable as super class

, где C1 фактически реализует Importable (поэтому он теоретически может быть преобразован в Importable).

Ответы [ 5 ]

32 голосов
/ 23 мая 2010

Использовать преобразование во время выполнения:

Class <? extends Importable>  c
    = Class.forName (s).asSubclass (Importable.class);

Это будет лаять с исключением во время выполнения, если s указывает класс, который не реализует интерфейс.

7 голосов
/ 23 мая 2010

Попробуйте:

Class<? extends Importable> klaz = Class.forName(s).asSubclass(Importable.class);

Вот некоторые фрагменты, иллюстрирующие проблемы:

Class<CharSequence> klazz = String.class; // doesn't compile!
// "Type mismatch: cannot convert from Class<String> to Class<CharSequence>"

Однако:

Class<? extends CharSequence> klazz = String.class; // compiles fine!

Так что для interface,вам определенно нужен верхний ограниченный символ подстановки.asSubclass соответствует предложению doublep.

API-ссылки

  • <U> Class<? extends U> asSubclass(Class<U> clazz)
    • Приводит этот Class объект для представленияподкласс класса, представленный указанным объектом класса.Проверяет, что приведение является действительным, и выдает ClassCastException, если это не так.Если этот метод завершается успешно, он всегда возвращает ссылку на этот объект класса.

Смежные вопросы

См. Также

2 голосов
/ 23 мая 2010

Нечто подобное может сработать:

Class<?> c1 = Class.forName(s);
Class<? extends Importable> c = c1.asSubclass(Importable.class);
return c.newInstance();

Остерегайтесь ClassCastException или NoClassDefFound, если вы ошиблись. Как говорит @polygenelubricants, если вы можете найти какой-то способ избежать Class.forName, тогда тем лучше!

0 голосов
/ 23 мая 2010

, где Importable - это интерфейс, а строка s - имя реализующего класса.

Компилятор не может этого знать, отсюда и ошибка.

Используйте актерский состав.Создавать построенный объект легче (потому что это проверенное приведение), чем сам объект класса.

Class<?> c = Class.forName(s);
Importable i = (Importable) c.newInstance();
return i;
0 голосов
/ 23 мая 2010

Проблема заключается в том, что Class.forName является статическим методом со следующим определением

public static Class forName (String className) выдает ClassNotFoundException

Поэтому он вообще не является связанным типом параметра икомпилятор определенно выдаст предупреждение о приведении здесь, так как он не может гарантировать, что имя строки класса всегда даст вам реализацию интерфейса.

Если вы точно знаете, что имя строки передано в методбудет реализация интерфейса, вы можете использовать аннотацию SuppressWarnings.Но я не думаю, что есть какой-либо другой более чистый способ использования forName с генериками

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...