【问题标题】:Generic type assignment says incompatible type for more restrictive assignment泛型类型分配表示不兼容类型以进行更严格的分配
【发布时间】:2015-02-16 13:49:06
【问题描述】:

我有一个以下类型的变量

Pair<String, Class<?>> test;

我正在尝试像这样创建它:

Class<? extends Animal> animal = Tiger.class;
test = Pair.create("tiger", animal);

代码给了我“不兼容的类型”(在创建 Pair with animal 时)。虽然变量测试定义允许任何类型的类,并且动物定义了任何动物子类的边界,这比原来的更严格。那么这个作业不应该有效吗?

【问题讨论】:

  • 我在 Java 中的泛型也遇到了同样的问题,它们是使用类型擦除实现的,这充其量是很不稳定的。如果你的测试也用过?扩展动物,它会工作。
  • @JeffWatkins 谢谢,但这没有任何意义,当 (Class>) 意味着它可以容纳任何类类型时,保持更多限制性类型应该没有问题。
  • 请发布 Pair.create 方法代码,或者至少是带有返回类型的签名
  • 这对我有用:pastebin.com/GFf8buMf
  • @guido 这是 android 库 android.util.Pair 中的一个标准类,这里是它的链接developer.android.com/reference/android/util/Pair.html

标签: java generics


【解决方案1】:

TigerAnimal 的子类型,但 Class&lt;Tiger&gt; 不是 Class&lt;Animal&gt; 的子类型。 Class&lt;Tiger&gt;Class&lt;Animal&gt; 的父级都是 Class&lt;?&gt;

同样,Pair&lt;String, Class&lt;? extends Animal&gt;&gt; 不是Pair&lt;String, Class&lt;?&gt;&gt; 的子类型,它们实际上是不同的对象,即使Class&lt;? extends Animal&gt;&gt;Class&lt;?&gt; 的子类型。

为了更容易理解,从集合的角度来考虑它:如果你有一个Pair&lt;String, List&lt;?&gt;&gt;,你给它分配了一个Pair&lt;String, List&lt;? extends Number&gt;&gt;;然后,您可以将String 添加到列表中。 http://ideone.com/dcXnWs

在 Java8 中,您的代码可以工作 http://ideone.com/AkK7Zv;老实说,我不确定编译器还做了什么(仍然需要深入研究新功能)。无论如何,正如您所看到的,以下示例的编译器错误非常具有解释性:

【讨论】:

  • Java 8 改进了类型推断(主要是在函数返回泛型类型时)。这可能是代码使用 java 8 的原因。有关更多信息,请参阅blog.decaresystems.ie/2014/04/09/…
  • 更具体地说,Java 8 知道返回赋值的类型,并为方法调用推断 &lt;String, Class&lt;?&gt;&gt;
【解决方案2】:

它在 Java 8 中工作的可能解释(改进了类型推断):

public static class Pair<A, B> {
        public static <A, B> Pair<A, B> create(A a, B b) {
                return new Pair<A, B>();
        }
}

public static class Animal {}
public static class Tiger extends Animal {}

public static final void main(final String[] args) {
        Class<? extends Animal> animal = Tiger.class;
        Pair<String, Class<?>> test = Pair.create("tiger", animal);
}

根据Java Generics Subtyping Rules

  1. 的确如此:Class&lt;? extends Animal&gt; extends Class&lt;?&gt;
  2. 这是错误的:Pair&lt;String, Class&lt;? extends Animal&gt;&gt; extends Pair&lt;String, Class&lt;?&gt;&gt;

因为 2. 它在 Java 7 中不起作用,但 Java 8 使用了 1.:

Pair<String, Class<?>> test = Pair.create("tiger", animal);

Java 8 推断参数 a 的类型为 String,而参数 b 的类型为 Class&lt;?&gt;。因为 1. 为真,它可以将第二个参数转换为 Class&lt;?&gt;,然后它适合变量 test 的类型。

因此,因为它可以在将单个参数传递给方法之前对其进行转换,所以它不必转换返回的结果(这是不可能的)。

【讨论】:

    猜你喜欢
    • 2021-07-05
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 2016-01-23
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多