Java 8 - 为期望泛型类型的方法提供原始类型参数会导致其返回类型被擦除

时间:2018-04-24 18:34:46

标签: java generics java-8

以下示例在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 :(得分:2)

JLS, Chapter 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

(似乎我似乎无法找到一天的答案,详细解释一个长问题,发布并在不久之后找到答案。)

答案 1 :(得分:1)

我无法真正找到java-7的问题(我会尝试更多),但似乎通过以下方式指定in the JLS

  

未从其超类或超接口继承的原始类型C的构造函数(第8.8节),实例方法(第8.4节,第9.4节)或非静态字段(第8.3节)M的类型是原始的在与C对应的泛型声明中对应于其类型擦除的类型。

认为就是这个,因为我在原始类型下找不到更能解释它的东西。或者,简单来说,一旦你使用原始类型,其他一切(甚至是不相关的东西)也将使用擦除类型。