当前位置: 首页 > 面试题库 >

在JDK 7中,类型推断比JDK 6更具限制性吗?

曹浩
2023-03-14
问题内容

我认为这可能与为什么List <?的泛型转换有关?在Sun JDK 6上成功将Set ..>扩展到List <Set ..>,但是在Oracle JDK
7上无法编译?

如果我们采用以下类,则它们可以在JDK 6下很好地编译:

public final class Foo<V> {

    private final V value;

    private Foo(final V value) {

        this.value = value;
    }

    public static <T, R extends T> Foo<T> of(final R value) {

        return new Foo<T>(value);
    }
}

final class Tester {

    @Test(groups="unit")

    public static void test() {

        bar(Foo.of(BigDecimal.ZERO));  // This line fails in JDK 7 but not JDK 6
    }

    private static void bar(final Foo<? extends Number> target) {

        assert target != null;
    }
}

但是,在JDK 7下,我收到以下错误:

[ERROR] \work\fsb-core\src\test\java\com\fsb\core\Foo.java:[42,8] error:
              method bar in class Tester cannot be applied to given types;

我认为在JDK 7中类型推断没有那么严格的限制(例如,添加构造函数推断)。但是,在这里,编译器拒绝在JDK 6下有效的类型。

这是一个错误吗?还是推理规则对方法变得更加严格?


问题答案:

严格根据规范,T不能进行推断(根据15.12.2.7),因此应将其视为Object

这可以看作是规范的失败。spec是这样推断的R:首先是约束R :> BigDecimal,其中:>means 是的超类型
。然后选择推理规则,R=BigDecimal因为它是满足约束的最具体的类型。

现在,由于T:>R,,T:>BigDecimal人们会认为这也应该产生T=BigDecimal

不幸的是,推理规则没有考虑T:>R在内。没有约束TT不能通过相同的原理来推断。

虽然很糟糕,但规格是规格。您的代码不应编译。Javac6在那里是错误的。

在Java 8中,推理规则有了很大的改进,使lambda表达式更易于使用。希望您的代码可以在Java 8中编译。



 类似资料:
  • 为什么Java可以推断出多个上限类型的共同祖先,而不能推断出下限类型的共同祖先? 更具体地说,请考虑以下示例:

  • 例如,我有一个Fruit和vitamin类的本体论。水果类只有橘子和香蕉为亚类,维生素类只有维他命C和维他命B为亚类。这些子类都是互不相交的。 我还提供了一个object属性,类Fruit作为域,类Vitamin作为范围。 然后,我定义了限制条件:“橘子提供一些维他命C”和“香蕉提供一些维他命B”。

  • 主要内容:1 Java8 类型推断的介绍,2 Java8 类型推断的案例1,3 Java8 类型推断的案例21 Java8 类型推断的介绍 类型推断是Java的一项功能,它使编译器可以查看每个方法调用和相应的声明以确定参数的类型。 Java在Java 8中提供了类型推断的改进版本。 1.1 Java8以前 在下面的声明中,我们在一侧提到了arraylist的类型。这种方法是在Java 7中引入的。在这里,您可以将第二面留为<>,并且编译器将通过引用变量的类型来推断其类型。 1.2 Java8以后

  • TypeScript 类型检查机制包含三个部分: 类型推断 类型保护 类型兼容性 本节介绍其中的类型推断,类型推断主要用于那些没有明确指出类型的地方帮助确定和提供类型,这是 TypeScript 的一种能力。 类型推断是有方向的,要注意区分从左向右和从右向左两种推断的不同应用。 1. 慕课解释 类型推断的含义是不需要指定变量类型或函数的返回值类型,TypeScript 可以根据一些简单的规则推断其

  • 01 模板类型推断机制 auto 推断的基础是模板类型推断机制,但部分特殊情况下,模板推断机制不适用于 auto 模板的形式可以看成如下伪代码 template<typename T> void f(ParamType x); // ParamType 即 x 的类型 调用可看成 f(expr); 编译期间,编译器用 expr 推断 T 和 ParamType,实际上两者通常不一致,比如 te