Неожиданное непроверенное предупреждение о сотворении, полученное при приведении к типу reified (неограниченный подстановочный знак) - PullRequest
0 голосов
/ 23 января 2019

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

Этот метод выдает предупреждение о неконтролируемой активации в указанной строке:

    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.

Два вопроса:

  1. Почему приведение к неограниченному подстановочному типу генерирует предупреждение в metadataForName(), но не в obtainMetadata()?
  2. Если аргумент типа для obtainMetadata() равен ? extends DateSerial, почему этот метод возвращает необработанный тип Optional?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...