java - 什么时候菱形语法在 Java 8 中不起作用?

标签 java

从 Java 7 开始,菱形语法并不总是适用于方法参数,例如Why does the diamond operator not work for java.util.Collections methods in Java 7? .该问题的答案提到 Java 8 中的目标类型推断解决了该问题。

是否还有不能使用菱形语法的剩余情况?

最佳答案

菱形运算符不能总是在 Java 8 中使用。改进 Java 8 中推理的最初计划 (JEP 101) 有两个目标:

  • 在方法上下文中添加对方法类型参数推断的支持
  • 在链式调用中添加对方法类型参数推断的支持

只实现了第一个。借用 JEP 中的示例,考虑以下类:

class List<E> {
   static <Z> List<Z> cons(Z head, List<Z> tail) { ... };
   E head() { ... }
}

在 Java 8 中,改进的方法上下文推断允许以下编译。对于 Java 7,它将失败并显示错误 expected List<Integer>, found List<Object>

List<Integer> l = List.cons(42, new List<>());

但是,需要推断链式调用的示例仍然不适用于 Java 8:

Integer i = new List<>().head();

JSR 335 的 D 部分包括关于为什么 Java 8 放弃了链式表达式推理的提示:

There has been some interest in allowing inference to "chain": in a().b(), passing type information from the invocation of b to the invocation of a. This adds another dimension to the complexity of the inference algorithm, as partial information has to pass in both directions; it only works when the erasure of the return type of a() is fixed for all instantiations (e.g. List). This feature would not fit very well into the poly expression model, since the target type cannot be easily derived; but perhaps with additional enhancements it could be added in the future.


还有一些更人为的例子,其中钻石不能使用。

如果 bug 计数,这不会用 jdk8u25 之前的 javac 编译。 (参见 JDK-8029002)

class Test {
  class C<T extends C<T>> {}
  void m() {
    C<?> i = new C<>();
  }
}

error: incompatible types: cannot infer type arguments for Test.C<>
    C<?> i = new C<>();
                  ^
    reason: inferred type does not conform to upper bound(s)
      inferred: Test.C<CAP#1>
      upper bound(s): Test.C<Test.C<CAP#1>>,Test.C<CAP#1>
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Test.C<CAP#1> from capture of ?

新的类型推断实现也存在性能问题 ( JDK-8051946 ),它会影响使用菱形运算符的代码。如果使用菱形运算符,则以下示例需要几分钟才能编译。

class Test {
  <T> T and(T a, T b) { return null; }
  class C<T> {}

  void g(String s) {}
  void g(Object s) {}

  void m() {
    g(
        and(
        and(
        and(
        and(
        and(
        and(
        and(new C<>(),
            new C<>()),
            new C<>()),
            new C<>()),
            new C<>()),
            new C<>()),
            new C<>()),
            new C<>()));
  }
}

关于java - 什么时候菱形语法在 Java 8 中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27134626/

相关文章:

java - Kotlin/Java 在 Int 类型的 switch 语句中使用枚举

java - 尝试在 android 中的 Strings.xml 中的 textView 中设置图像

java - 方法被重写后,类不可序列化

java - 随机生成范围内的奇数

Java:JRadioButton 上的 ActionEvent 和 ItemEvent 有什么区别?

java - 如何转换java中的默认文件路径?

java - 无法访问主目录 : Permission denied java. lang.IllegalArgumentException: 没有匹配接口(interface) SourceDataLine 的行

java - 简单猜谜游戏中的记分牌

Java8 Streams - 使用 Stream Distinct 删除重复项

java - 使用 Apache Camel AdviceWith 和 weaveById 进行测试