通用生产者和消费者

时间:2015-10-27 10:44:05

标签: java generics

我正在设计一个容器类,用于保存

的一对实现
public interface MetaData<ValueType>{
    public String getName();
}

ValueType Type参数的对应值。所以我写了这个(强制执行一些不变的):

public final class ParametersImpl implements Parameters{

    private final Map<MetaData<?>, Object> parameters;
    {
        parameters = new HashMap<>();
    }

    @Override
    public Object getValue(MetaData<?> pmd) {
        return parameters.get(pmd);
    }

    @Override
    public <M> void put(MetaData<M> p, M value) {
        parameters.put(p, value);
    }
}

其中

public interface Parameters {

    public Object getValue(MetaData<?> pmd);
    public <M> void put(MetaData<M> p, M value);
}

当客户端调用方法Object getValue(MetaData<?> pmd)时,他们必须进行显式转换:

MetaData<List<Integer>> metaData;
Paramters params;
List<Integer> list= new ArrayList<>();
//intialization
params.put(metaData, list);
//do some other
List<Integer> lst = (List<Integer>) params.getValue(metaData);

虽然演员表是完全安全的,但我想避免它并提供某种通用方法。但是当我尝试这个宣言时:

public <M> M getValue(MetaData<M> pmd);

我在实现中遇到了编译错误:

public <M> M getValue(MetaData<M> pmd) {
    return parameters.get(pmd); //cannot convert capture-of-#1 to M
}

问题: 有没有办法以任何方式生成方法public Object getValue(MetaData<?> pmd);

1 个答案:

答案 0 :(得分:2)

您只需要转换从地图中检索到的值:

public <M> M getValue(MetaData<M> pmd) {
  return (M) parameters.get(pmd);
}

但是此时编译器抱怨它无法检查强制转换。这是什么意思?好吧,Java源代码中的普通强制转换用(SomeType) val表示 - 编译器检查操作是否完全非法(例如,您不能转换String引用到Integer)并发出一个在运行时执行的字节码,它可能会抛出ClassCastException

当您使用类型变量强制转换引用时,编译器无法发出这样的字节码,因为类型变量在运行时不存在 - 因此会发出编译警告。你应该:

  • 确保使用正确的值填充地图
  • 使用@SuppressWarnings("unchecked")
  • 取消警告