关于Java:泛型中的不可转换类型

Inconvertible types in Generics

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Is `List` a subclass of `List`? Why aren’t Java’s generics implicitly polymorphic?

我需要帮助理解发生了什么。

我有一个接口

1
2
3
4
5
6
public interface Foo {

  Map<String, ParameterValue> getParameters();
}

public interface ParameterValue { }

以及foo的实现。

1
2
3
4
5
6
7
8
9
10
class FooImpl implements Foo {
   Map<String, ParameterValueImpl> parameters = new HashMap<String, ParameterValueImpl>();
   //ParameterValueImpl an implementation of ParameterValue

@Override
    public Map<String, ParameterValue> getParameters() {
        return ((Map<String,ParameterValue>) parameters);
    }  

}

我得到以下错误

1
2
3
4
5
6
7
[ERROR] Failed to execute goal
failure [ERROR]
src/main/java/domainJPA/model/FooImpl.java:[92,45]
inconvertible types [ERROR] found   :
java.util.Map<java.lang.String,domainJPA.model.ParameterValueImpl>
[ERROR] required:
java.util.Map<java.lang.String,domain.model.ParameterValue>

我必须在foo的接口中使用parameterValue,在fooimpl中,我必须只实现parameterValue(parameterValueImpl),因为它是@entity,JPA需要它。

我怎样才能编译这段代码?

编辑

如果我按照其中一个答案中的建议将代码更改为? extends ParameterValue,那么我就不能使用foo接口。

以下代码导致编译错误:The method put(String, capture#8-of ? extends ParameterValue) in the type Map is not applicable for the arguments (String, ParameterValueImpl)

foo.getParameters().put("test", new ParameterValueImpl);


想想看——如果getParameters()的返回值实际上是一个Map,那么您就可以向源自ParameterValue而不是ParameterValueImpl的映射中添加一个值。这样做会破坏类型安全。

您有两个选项可以更正此问题:

  • getParameters()中,将地图复制到正确类型的新地图中。
  • 使用Map作为FooImpl.parameters的类型。

  • 您可以将接口方法更改为:

    1
    Map<String, ? extends ParameterValue> getParameters();

    现在,您可以返回String和任何实现ParameterValue的类型的映射。

    那么在实现这个方法时就不需要进行类型转换了。

    1
    2
    3
    public Map<String, ? extends ParameterValue> getParameters() {
        return parameters;
    }

    或者,由于您可以在ParameterType引用中存储ParameterValueImpl类型实例,因此您也可以将FooImpl类中的Map更改为:

    1
    Map<String, ParameterValue> parameters = new HashMap<String, ParameterValue>();

    那你原来的方法就行了。