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

Diamond语法何时在Java 8中不起作用?

黄扬
2023-03-14
问题内容

从Java 7开始,钻石语法在方法参数中并不总是有效,例如,为什么钻石运算符不适用于Java7中的java.util.Collections方法?。该问题的答案提到Java 8中的目标类型推断可解决该问题。

是否还有其他情况无法使用菱形语法?


问题答案:

Diamond运算符不能总是在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为什么放弃链式表达式推理的提示:

允许推理到“链”已经引起了一些兴趣:在a()。b()中,将类型信息从b的调用传递到a的调用。由于部分信息必须在两个方向上传递,这为推理算法的复杂性增加了另一个维度。它仅在所有实例化(例如List)的a()返回类型的擦除固定后才起作用。由于无法轻松导出目标类型,因此该功能不太适合多表达式模型。但也许有其他增强功能可以在将来添加。

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

如果算错了,那么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<>()));
  }
}


 类似资料:
  • 我对方法引用在Java8中是如何工作的有些困惑。我编写了下面的代码段用于过滤文件夹中的隐藏文件。他们正在产生正确的结果。我不理解->listFiles方法的方法签名是如何在这个代码段的选项2中工作的。 这是我在Java8文档中发现的

  • 我试过如下所示,但在两种情况下显示的时间都是相同的?我做错了什么。 “当前日期”时间显示与“12小时后”相同...

  • 我试图查询存在特定字段的日期范围。这似乎很容易,但我感觉到关键字“exists”在文档中发生了变化。我在5.4。https://www.elastic.co/guide/en/elasticsearch/reference/5.4/query-dsl-exists-filter.html 我使用@timestamp表示日期,并且字段“error_data”在映射中,只有在发现错误条件时才出现。 以

  • 问题内容: 我是一个新手,Python和目前正在学习像控制流的命令,等 该语句工作正常,但是当我编写或命令时,解释器给我一个语法错误。我使用的是Python 3.2.1,问题出在其本机解释器和IDLE中。 我遵循的是 《 Python的字节》一 书中给出的内容。如您所见,并且给出了 Invalid Syntax 。 为什么会这样呢?我在IDLE和交互式python中都遇到了问题。我希望语法正确。

  • 我正在使用演示APi(http://dummy.restapiexample.com/update) 我有一个响应类UpdateResponse 我有一个Api类和一个APIInterface 和对话框而不是主活动 在APIInterface中使用PUT方法有一个@path(id)和三个@fields(name、salary、age) 下面是UpdateResponse类代码 Api接口代码如下

  • 问题内容: 这按预期工作,测试失败(由于haltTesting()),并重复了2次 但是因为我在一堂课中有多个测试,所以我在课上定义了repeatAnalyzer 但是文档没有重复测试,它说: 类级别的@Test注释的作用是使该类的所有公共方法都成为测试方法,即使它们没有被注释也是如此。如果要添加某些属性,仍然可以在方法上重复@Test批注。 所以应该是可能的,还是我期望得到错误的结果? 问题答案