【问题标题】:Failing to compile correlated Java Generics parameters with wildcards无法使用通配符编译相关的 Java 泛型参数
【发布时间】:2013-05-17 15:47:21
【问题描述】:

以下 Java 小示例由于原因不明而无法编译:

package genericsissue;

import java.util.ArrayList;
import java.util.List;

interface Attribute<V> {}

interface ListAttribute extends Attribute<List<?>> {}

public class Context {
    public <T, A extends Attribute<T>> void put(Class<A> attribute, T value) {
        // implementation does not matter for the issue
    }

    public static void main(String[] args) {
        Context ctx = new Context();
        List<?> list = new ArrayList<String>();
        ctx.put(ListAttribute.class, list);
    }
}

带有 ctx.put 的行产生以下错误:

Context.java:18: <T,A>put(java.lang.Class<A>,T) in genericsissue.Context cannot be applied to (java.lang.Class<genericsissue.ListAttribute>,java.util.List<capture#35 of ?>)

如果不使用通配符,则属性模式可以正常工作。

有什么解释为什么编译器不接受通配符类型的值吗?

【问题讨论】:

  • 这可能是类型推断系统的限制。试试:ctx.&lt;List&lt;?&gt;, ListAttribute&gt;put(ListAttribute.class, list).
  • 您的问题的出色表述! SSCCE、错误信息等

标签: java generics nested-generics


【解决方案1】:

问题是,list 的参数类型并不是真正的List&lt;?&gt;。编译器首先执行“通配符捕获”以将其类型转换为List&lt;x&gt; for some x。通常这会提供更多信息和帮助。但不是你的情况。它促使类型推断认为T=List&lt;x&gt;,但ListAttribute 没有扩展Attribute&lt;List&lt;x&gt;&gt;

您可以提供显式类型参数来解决它

ctx.<List<?>, ListAttribute>put(ListAttribute.class, list);
      (T)      (A)

【讨论】:

  • 此解决方案满足编译器,但不满足最初为避免类型转换和显式类型参数等冗长提示而创建的模式。
  • @iterator - 您的原始代码现在使用不同的推理规则在 java8 中编译。但是,它可能也应该在 java7 中工作,但 javac 中有一个错误。不确定。
【解决方案2】:

替换

public <T, A extends Attribute<T>>

public <T, A extends Attribute<? super T>>

【讨论】:

  • 既然我们不知道put 的实现,你怎么能认为这没问题?
  • 那么它是类型安全的吗?因为在我看来,我可以将超类型层次结构中的所有实例作为值,这不是我想要允许的。
  • 我认为我们可以假设这没问题,因为您必须记住 value 可能已经是 T 的任何子类。所以如果valueStringA 可能是Attribute&lt;String&gt;Attribute&lt;CharSequence&gt;Attribute&lt;Object&gt;,就像现在一样。唯一能阻止的是从A生成一个T,这似乎是合理的。
  • 想了一会儿,听起来很有道理。所以这确实是解决方案,它是类型安全的,因为 Attribute 类型可以在类型层次结构中更高。它现在就像一个魅力。
  • @MarkPeters - 没关系,但没必要; T 在推理过程中足够空闲,所以 Attribute&lt;T&gt; 应该可以工作。顺便说一句,OP 的代码在 Java8 中编译。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
  • 2021-04-22
相关资源
最近更新 更多