加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java有界泛型:类型推断错误? (方法调用,JLS 15.12.2.7)

发布时间:2020-12-14 05:15:02 所属栏目:Java 来源:网络整理
导读:有关以下代码片段: import java.util.List;public class Main { interface Interface1T {} interface Interface2T extends Interface1T {} static class Bound {} interface BoundedI1T extends Bound extends Interface1T {} interface BoundedI2T extends
有关以下代码片段:
import java.util.List;

public class Main {
    interface Interface1<T> {}
    interface Interface2<T> extends Interface1<T> {}
    static class Bound {}
    interface BoundedI1<T extends Bound> extends Interface1<T> {}
    interface BoundedI2<T extends Bound> extends Interface2<T> {}

    public static void main(String[] args) {
        test((List<BoundedI2<?>>) null);
        //test2((List<BoundedI2<?>>) null);
    }

    public static void test(List<? extends Interface2<? extends Bound>> list) { test2(list); }

    public static void test2(List<? extends Interface1<? extends Bound>> list) {}
}

编译器第一次调用就OK了,但是如果我取消了第二次调用,则会抱怨.这是类型推理系统中的错误,还是有人可以解释为什么JLS中的推理规则在这里失败?

测试了6u43和7u45 Oracle JDK.

更新:似乎像eclipsec接受它很好.不幸的是,我不能真正改变我们的工具链:P,但有兴趣的是在编译器中找到差异.

由ideone(酷工具btw)打印出来的错误信息:

Main.java:12: error: method test2 in class Main cannot be applied to given types;
        test2((List<BoundedI2<?>>) null);
        ^
  required: List<? extends Interface1<? extends Bound>>
  found: List<BoundedI2<?>>
  reason: actual argument List<BoundedI2<?>> cannot be converted to List<? extends Interface1<? extends Bound>> by method invocation conversion

更新2:这编译好,这表明编译器认为BoundedI2<?>可分配给Interface1扩展Bound>,这似乎更直接地违反了JLS:

public class Main {
    interface Interface1<T> {}
    interface Interface2<T> extends Interface1<T> {}
    static class Bound {}
    interface BoundedI1<T extends Bound> extends Interface1<T> {}
    interface BoundedI2<T extends Bound> extends Interface2<T> {}

    public static void main(String[] args) {
        test((List<BoundedI2<?>>) null);
        //test2((List<BoundedI2<?>>) null);
        test3((BoundedI2<?>) null);
    }

    public static void test(List<? extends Interface2<? extends Bound>> list) { test2(list); }

    public static void test2(List<? extends Interface1<? extends Bound>> list) {}
    public static void test3(Interface1<? extends Bound> instance) {}
}

解决方法

看起来命令行编译器同时处理一些困难

> BoundedI2在T上是通用的事实,它必须是“绑定”
> Interface2扩展Interface1的事实

至少没有正确地确定BoundedI2.奇怪的是,在同一个JDK上配置的Eclipse编译它很好…注意,Eclipse使用它的内部编译器,以便在键入时处理增量重新编译,因此它根本不会调用JDK的编译器(请参阅org / eclipse / jdt / internal / compiler包).

这个修改使得它可以在Eclipse和命令行中编译,通过强制BoundedI2是一个具体的类型,而不是类型推断:

import java.util.List;

public class PerfTest {
    interface Interface1<T> {}
    interface Interface2<T> extends Interface1<T> {}
    static class Bound {}
    interface BoundedI1<T extends Bound> extends Interface1<T> {}
    interface BoundedI2<T extends Bound> extends Interface2<T> {}
    static class Actual extends Bound {}

    public static void main(String[] args) {
        test((List<BoundedI2<Actual>>) null);
        test2((List<BoundedI2<Actual>>) null);
    }

    public static void test(List<? extends Interface2<? extends Bound>> list) { test2(list); }

    public static void test2(List<? extends Interface1<? extends Bound>> list) {}
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读