Java 8 - Предоставление необработанного аргумента типа методу, ожидающему универсального типа, приводит к удалению его возвращаемого типа - PullRequest
0 голосов
/ 24 апреля 2018

Следующий пример успешно компилируется в Java 7 и не компилируется в Java 8 (и новее).

public abstract class Example<T> 
{
    public T method() 
    {
        return method(new HashMap());
    }

    abstract T method(Map<String, String> arg);
}

Java 7:

BUILD SUCCESSFUL in 1s

Java 8:

> Task :compileJava FAILED
C:\dev\projects\Java8\src\main\java\example\Example.java:10: error: incompatible types: Object cannot be converted to T
        return method(new HashMap());
                     ^
  where T is a type-variable:
    T extends Object declared in class Example

Ошибка выше означает, что method(new HashMap()) вернул Object вместо ожидаемого T.

Чтобы избежать этой ошибки в Java 8, я должен предоставить аргумент универсального типа, то есть изменить new HashMap() наnew HashMap<>().

Тревожная часть заключается в том, что ошибка, вызванная необработанным аргументом типа, переданным method(Map<String, String>), фактически связана с тем, что этот метод возвращает Object вместо T.Поэтому я могу ожидать:

T result = method(new HashMap<>());

..., но:

Object result = method(new HashMap());

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

Есть ли обоснованиеа применимо объяснение такого поведения?Я знаю об изменениях, затрагивающих обобщение, сделанное в Java 8, но ничего не соответствует этому конкретному случаю.

Спасибо за ваши ответы.

Ответы [ 2 ]

0 голосов
/ 24 апреля 2018

JLS, глава 15.

15.12.2.6.Тип результата метода и выбрасываемые типы

Тип результата выбранного метода определяется следующим образом:

[...] если для применения метода было необходимо непроверенное преобразование, тогда тип результатаэто стирание (§4.6) объявленного типа возвращаемого значения метода.[...]

Он был поднят в JDK-6791481 .

Если бы я сделал это public abstract class Example<T extends java.lang.Exception>, то я бы получил error: incompatible types: Exception cannot be converted to T.


(Опять же, мне кажется, что мне не удалось найти ответ за день, разработать длинный вопрос, опубликовать его и вскоре найти ответ.)

0 голосов
/ 24 апреля 2018

Я не могу найти проблему для Java-7 (я попробую больше), но, похоже, это указано в JLS через:

Тип конструктора (§8.8), метода экземпляра (§8.4, §9.4) или нестатического поля (§8.3) M необработанного типа C, который не унаследован от его суперклассов или суперинтерфейсов, является необработанным тип, который соответствует стиранию его типа в общем объявлении, соответствующем C.

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

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