Преобразование Class.forName ("java.lang.String") / 'Class.forName ("some_str_var") "в Class <String>: почему первое вызывает предупреждение о непроверенном компиляторе? - PullRequest
0 голосов
/ 25 декабря 2018

Эта строка кода

 Class<String> cls =  (Class<String>) Class.forName("java.lang.String");

Выдает предупреждение компилятора Type safety: Unchecked cast from Class<capture#1-of ?> to Class<String>

Кроме того, согласно определению API, возвращается: Class<?>:

Class<?> Class.forName(String arg)

Я не понимаю, почему преобразование из Class<?> в Class<String> считается непроверенным (то есть компилятор не может проверить, возможно ли такое приведение во время компиляции).

Если это было

Class<String> cls =  (Class<String>) Class.forName("some_str_var");

Я мог бы понять, что компилятор не может знать тип возвращаемого значения Class.forName () во время компиляции (, поскольку аргумент является переменной, а не литералом ), а во время выполнения информация о типе стирается.

Но Class.forName("java.lang.String") является очевидным Class<?> во время компиляции (и переменная cls в LHS по-прежнему Class<String>), информация о типе еще не стерта (компилятор видит исходный код, а не байт-код со стертымtype-info), и компилятор может проверить все.

Ответы [ 2 ]

0 голосов
/ 25 декабря 2018

Класс, представленный строкой "java.lang.String", доступен во время компиляции, потому что он является частью стандартной библиотеки.Таким образом, компилятор может, в принципе, выполнить class.forName() и проверить, что возвращаемый класс соответствует объявлению типа.

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

Так что компилятор просто берет простейший, самый общий подход.Компиляторы сложны, и дизайнеры часто предпочитают не добавлять больше сложности, что принесет пользу только нескольким особым случаям.

Я также подозреваю, что возможность пользовательских загрузчиков классов может усложнить реализацию этой проверки;классы, доступные во время компиляции, вероятно, не гарантированно (согласно спецификации языка Java) будут теми, которые доступны во время выполнения, даже для стандартной библиотеки - даже если они обычно будут одинаковыми.

0 голосов
/ 25 декабря 2018

Компилятор не дает никакой особой обработки строковой константе "java.lang.String" в этом вызове:

Class.forName("java.lang.String")

Class.forName - это только один из многих методов, так же как и параметр, переданный емуэто всего лишь одна из многих строк.

Таким образом, следующие два значения одинаковы для компилятора (что касается типа возвращаемого значения):

String className = "java.lang.String";
Class<String> stringClass = Class.forName(className);

И

Class<String> stringClass = Class.forName("java.lang.String");

Компилятор не проверяет постоянный аргумент, чтобы сделать вывод, что это обязательно будет Class<String>.Если вы хотите получить Class<String> безопасным для типа способом, вы должны использовать:

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