简体   繁体   English

类型安全合并 Map 与多种类型的值; `不兼容的类型 java.lang.Object 无法转换为捕获 #1 的 ?`

[英]Type safe merging of Map with multiple types for its value; `incompatible types java.lang.Object cannot be converted to capture#1 of ?`

I have a container class which has a Map which is carrying multiple types for its value.我有一个容器类,它有一个Map ,它携带多种类型的值。 To make it type safe from the external point of view, the key itself has a generic type, indicating what the type of the value will be.为了从外部的角度来看是类型安全的,键本身有一个泛型类型,指示值的类型。

The key provides some basic facilities to look up items and merge their values.键提供了一些基本的工具来查找项目并合并它们的值。 (There might be different merging rules for the type of value that is found). (找到的值类型可能有不同的合并规则)。

public abstract class Key<T> {
  @SuppressWarnings("unchecked")
  T get(Map<Key<?>, Object> data) {
      return (T) data.get(this);
  }

  /** 
    * This must be provided by the implementation. 
    *
    * @param old the old value
    * @param new the new value
    * @returns the merged value
    */ 
  abstract T merge(T old, T new);  
}

The Container class then looks like this. Container类看起来像这样。

public class Container {

  private final Map<Key<?>, Object> data = new HashMap<>();

  public <T> Optional<T> get(Key<T> key) {
    return Optional.ofNullable(key.get(data));
  }

  public <T> Container set(Key<T> key, T value) {
    data.put(key, value);
    return this;
  }

  @SuppressWarnings("unchecked")
  public <T> Container merge(Key<T> key, T newValue) {
    data.compute(key, (k, oldValue) -> key.merge((T) oldValue, newValue));
    return this;
  }


  public Container mergeAll(Container that) {
    //this does not compile: incompatible types java.lang.Object cannot be converted to capture#1 of ?
    that.data.forEach((key, value) -> this.data.merge(key, value, key::merge));
    return this;
  }
}

All of this works fine, apart from the last mergeAll method.除了最后一个mergeAll方法之外,所有这些都可以正常工作。 It is looking at all the keys of the that container and merge their values with those of the this container.它正在查看that容器的所有键并将它们的值与this容器的值合并。

However the key::merge doesn't compile with an error incompatible types java.lang.Object cannot be converted to capture#1 of ?但是, key::merge无法编译并出现错误incompatible types java.lang.Object cannot be converted to capture#1 of ? . .

In the single merge() method I got around it with a type cast to (T) .在单个merge()方法中,我通过将类型转换为(T)来解决它。 But in this case I don't have a generic type, it is ?但在这种情况下,我没有泛型类型,它是? , but I cannot do something like: (key, oldValue) -> key.merge((?) oldValue, (?) value) because you cannot cast to (?) . ,但我不能做这样的事情: (key, oldValue) -> key.merge((?) oldValue, (?) value)因为你不能转换为(?)

Is there a way around this?有没有解决的办法? Or a better pattern to implement what I am trying to achieve?或者更好的模式来实现我想要实现的目标?

You should be able to fix this by writing:您应该能够通过编写以下内容来解决此问题:

public Container mergeAll(Container that) {
  that.data.forEach((key, value) -> this.data.merge(key, value, ((Key<Object>) key)::merge));
  return this;
}

In your example, key has an unbounded wildcard type Key<?> , so methods accepting generic parameters cannot accept anything but null .在您的示例中, key具有无界通配符类型Key<?> ,因此接受泛型参数的方法只能接受null As the values passed to merge are of type Object , you can cast your key to Key<Object> .由于传递给merge的值属于Object类型,因此您可以将keyKey<Object>

Another solution might probably be to change Key<?> to Key<Object> if this is applicable in your situation.如果这适用于您的情况,另一种解决方案可能是将Key<?>更改为Key<Object>

I don't think it'll get any more type safe than this, because the map Map<Key<?>, Object> data has no hint for the compiler that the class of the value is actually supposed to be the generic type of the key.我认为它不会比这更安全,因为映射Map<Key<?>, Object> data没有提示编译器该值的类实际上应该是钥匙。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 修复 java 中的错误:不兼容的类型:java.lang.Object 无法转换为 capture#1 of? - Fixing error in java: incompatible types: java.lang.Object cannot be converted to capture#1 of? 不兼容的类型:java.lang.Class<capture#1 of ?> 无法转换为 - Incompatible types: java.lang.Class<capture#1 of ?> cannot be converted to 不兼容的类型:推理变量T具有不兼容的边界等式约束:捕获#1的? 扩展java.lang.Object - incompatible types: inference variable T has incompatible bounds equality constraints: capture#1 of ? extends java.lang.Object 不兼容的类型:java.lang.Object无法转换为T - incompatible types : java.lang.Object cannot be converted to T 错误:类型不兼容:java.lang.Object 无法转换为 E - Error: incompatible types: java.lang.Object cannot be converted to E EasyMock Java:不兼容的类型:java.lang.ClassLoader无法转换为java.lang.Class <capture#1 of ? extends > - EasyMock java: incompatible types: java.lang.ClassLoader cannot be converted to java.lang.Class<capture#1 of ? extends > 修复 SQL 错误不兼容类型:capture#1 of? 无法转换为 int - Fix SQL error incompatible types: capture#1 of ? cannot be converted to int 不兼容的类型:java.lang.Object无法转换为java.lang.String - incompatible types: java.lang.Object cannot be converted to java.lang.String 不兼容的类型:java.lang.Object无法转换为java.lang.String吗? - incompatible types: java.lang.Object cannot be converted to java.lang.String? 无与伦比的类型:java.lang.Class<capture#1 of ? extends T[]> 和 java.lang.Class<java.lang.Object[]> - Incomparable types: java.lang.Class<capture#1 of ? extends T[]> and java.lang.Class<java.lang.Object[]>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM