Необработанные типы и неограниченные символы
Ни в одном из предыдущих ответов действительно не говорилось о том, почему вы предпочитаете Class<?>
, а не Class
, поскольку на первый взгляд кажется, что он не предлагает больше информации, чем последний.
Причина в том, что необработанный тип , то есть Class
, не позволяет компилятору выполнять проверки универсального типа. То есть, если вы используете необработанные типы, вы подверните систему типов Например:
public void foo(Class<String> c) { System.out.println(c); }
Может быть вызван таким образом (он будет скомпилирован и run):
Class r = Integer.class
foo(r); //THIS IS OK (BUT SHOULDN'T BE)
Но не по:
Class<?> w = Integer.class
foo(w); //WILL NOT COMPILE (RIGHTLY SO!)
Всегда используя не необработанную форму, даже если вы должны использовать ?
, потому что вы не можете знать, что является параметром типа (или ограничен), вы позволяете компилятору более полно рассуждать о правильности вашей программы. чем если бы вы использовали сырые типы.
<Ч />
Зачем вообще необработанные типы?
Спецификация языка Java говорит:
Использование необработанных типов разрешено только в качестве уступки совместимости с устаревшим кодом
Вы всегда должны избегать их. Неограниченный подстановочный знак ?
, вероятно, лучше всего описан в другом месте, но по существу означает "это параметризовано для некоторого типа, но я не знаю (или не волнуюсь), что это такое" . Это не то же самое, что raw types , которые являются мерзостью и не существуют в других языках с обобщениями, такими как Scala .
<ч />
Почему параметризован класс?
Ну, вот пример использования. Предположим, у меня есть некоторый интерфейс службы:
public interface FooService
И я хочу внедрить его реализацию, используя системное свойство, чтобы определить используемый класс.
Class<?> c = Class.forName(System.getProperty("foo.service"));
На данный момент я не знаю, что мой класс имеет правильный тип :
//next line throws ClassCastException if c is not of a compatible type
Class<? extends FooService> f = c.asSubclass(FooService.class);
Теперь я могу создать FooService
:
FooService s = f.newInstance(); //no cast