钻石语法什么时候在Java 8中不起作用? [英] When does diamond syntax not work in Java 8?

查看:466
本文介绍了钻石语法什么时候在Java 8中不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从Java 7开始,菱形语法并不总是在方法参数中起作用,例如为什么钻石运算符不适用于Java 7中的java.util.Collections方法?。该问题的答案提到Java 8中的目标类型推断修复了这个问题。

As of Java 7, diamond syntax did not always work in method arguments, e.g. Why does the diamond operator not work for java.util.Collections methods in Java 7? . The answer to that question mentions that target type inference in Java 8 fixes that issue.

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

Are there any remaining cases where diamond syntax cannot be used?

推荐答案

钻石操作符不能总是在Java 8中使用。最初计划改进Java 8中的推理( JEP 101 )有两个目标:

The diamond operator cannot always be used in Java 8. The original plan to improve inference in Java 8 (JEP 101) had two goals:


  • 添加支持方法上下文中的方法类型参数推断

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

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

Only the first was implemented. Borrowing the example from the JEP, consider the following class:

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

在Java 8中,改进的方法上下文推断允许以下编译。使用Java 7,它将失败,错误期望List< Integer> ;,找到List< Object>

In Java 8, the improved method context inference allows the following to compile. With Java 7, it would fail with the error expected List<Integer>, found List<Object>

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

但是,需要推断链式调用的示例仍无法与Java 8一起使用:

However, examples that require inference of chained calls still don't work with Java 8:

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

JSR 335 包含一个提示,说明为什么链接表达式推断被Java 8抛弃:

Section D of JSR 335 includes a hint about why chained expression inference was abandoned for Java 8:


允许推断链有一些兴趣:在a()。b()中,将类型信息从b的调用传递给a的调用。这为推理算法的复杂性增加了另一个维度,因为部分信息必须在两个方向上传递;只有当a()的返回类型的擦除对于所有实例化(例如List)都是固定的时,它才有效。此特征不适合多聚表达模型,因为目标类型不易导出;但也许有额外的增强功能可以在将来添加。

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.






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


There are also some more contrived examples where diamond can't be used.

如果错误计数,则不能在jdk8u25之前使用javac进行编译。 (参见 JDK-8029002

If bugs count, this doesn't compile with javac prior to jdk8u25. (see 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 )新的类型推理实现可以使用菱形运算符影响代码。如果使用菱形运算符,以下示例需要几分钟才能编译。

There's also a performance issue (JDK-8051946) with the new type inference implementation that can affect code using the diamond operator. The following example takes minutes to compile if the diamond operator is used.

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 8中不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆