Я думал, что приведение к неограниченному подстановочному типу никогда не сгенерирует предупреждение «непроверенное приведение», потому что неограниченные подстановочные типы повторно определены, и поэтому информация о типе, необходимая для безопасного завершения приведения, будет присутствовать во время выполнения, то есть «приведение к универсальный экземпляр класса любого (неизвестного) типа. "
Этот метод выдает предупреждение о неконтролируемой активации в указанной строке:
private static DateSerial.Metadata<?> metadataForName ( String className ) {
Class<? extends DateSerial> cls;
try {
cls = Class.forName(className).asSubclass(DateSerial.class);
} catch (ClassNotFoundException ex) {
return null;
}
--> DateSerial.Metadata<?> result = (DateSerial.Metadata<?>) Kernel
.obtainMetadata(cls)
.orElse(null);
return result;
}
Метод obtainMetadata()
возвращает Optional<T>
, где <T>
- параметр ограниченного типа <T extends DateSerial<T>>
. Как вы можете сделать из приведенного выше кода, аргумент типа, предоставленный для <T>
, равен ? extends DateSerial
. Ниже приведен фрагмент метода obtainMetadata
:
static <D extends DateSerial<D>> Optional<DateSerial.Metadata<D>>
obtainMetadata ( Class<D> cls ) {
Optional<Method> exe = Arrays
.stream(cls.getDeclaredMethods())
:
:
.findAny();
DateSerial.Metadata<?> k; // returned object must have type Metadata.class
try {
k = (DateSerial.Metadata<?>) exe // checked cast
.get().invoke(null);
}
catch (... ex) { return Optional.empty(); }
if (k == null || (k.getImplClass() != cls)) return Optional.empty();
@SuppressWarnings("unchecked")
DateSerial.Metadata<D> result = (DateSerial.Metadata<D>) k;
return Optional.of(result);
}
Этот метод рефлексивно ищет метод доступа к объекту метаданных и вызывает его. Вызванный метод должен иметь возвращаемый тип Metadata.class. Обратите внимание, что локальной переменной k
присваивается приведение к неограниченному подстановочному типу. Эта строка не выдает предупреждение.
К концу этого метода я доказал, что объект метаданных имеет тот же тип, что и предоставленный аргумент Class<D>
, и поэтому я могу безопасно выполнить приведение к возвращаемому типу (предупреждение подавлено, потому что я доказал, что это безопасно). Если <D>
равно ? extends DateSerial
, я ожидаю, что тип возвращаемого значения будет Optional<Metadata<? extends DateSerial>>
, но это не так. По причинам, которые мне не ясны, тип возвращаемого значения с указанным выше аргументом типа является необработанным типом Optional
.
Два вопроса:
- Почему приведение к неограниченному подстановочному типу генерирует предупреждение в
metadataForName()
, но не в obtainMetadata()
?
- Если аргумент типа для
obtainMetadata()
равен ? extends DateSerial
, почему этот метод возвращает необработанный тип Optional
?