使用隐式Lambda时出现不兼容的类型错误

ncsibra

我正在使用Java 8,并且对JUnit和AssertJ使用以下测试代码:

@Test
public void test() {
    List<Number> actual = new ArrayList<>();
    actual.add(Double.valueOf(1));
    actual.add(Integer.valueOf(1));
    actual.add(Long.valueOf(1));

    List<Class<? extends Number>> expected = new ArrayList<>();
    expected.add(Double.class);
    expected.add(Integer.class);
    expected.add(Long.class);

    // Just information how IDEA is generating types for the different statements
    ListAssert<? extends Class<? extends Number>> implicitLambda = assertThat(actual).extracting(t -> t.getClass());
    ListAssert<Class<? extends Number>> explicitLambda = assertThat(actual).extracting((Extractor<Number, Class<? extends Number>>) t -> t.getClass());
    ListAssert<Class<?>> methodReference = assertThat(actual).extracting(Number::getClass);

    // Does not compile
    // Error:(31, 84) java: incompatible types: java.util.List<java.lang.Class<? extends java.lang.Number>> cannot be converted to java.lang.Iterable<? extends java.lang.Class<capture#1 of ? extends java.lang.Number>>
    assertThat(actual).extracting(t -> t.getClass()).containsExactlyElementsOf(expected);

    // Compile because of explicit types
    assertThat(actual).extracting((Extractor<Number, Class<? extends Number>>) t -> t.getClass()).containsExactlyElementsOf(expected);

    // Compile, but don't understand why
    assertThat(actual).extracting(Number::getClass).containsExactlyElementsOf(expected);

}

在第一个断言中,我遇到了一个编译错误:
Error:(31, 84) java: incompatible types: java.util.List<java.lang.Class<? extends java.lang.Number>> cannot be converted to java.lang.Iterable<? extends java.lang.Class<capture#1 of ? extends java.lang.Number>>
我有以下问题:

  1. 确实是第一个断言中的lambda的返回类型<? extends Class<? extends Number>
    我只是依靠IDEA生成的局部变量。
  2. 如果是,那为什么呢?getClass文档说,
    The actual result type is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called.
    如果我理解正确,它应该是Class<? extends Number>
  3. 我应该使用哪种工具查看隐式lambda的类型?我可以使用JDK中的某些工具进行检查吗?
  4. 为什么带有方法引用的最后一个断言会编译?如果它确实返回了Class<?>,那么我理解了,但是为什么返回类型与此隐式lambda不同?

相关的AssertJ文档:
AbstractIterableAssert
AbstractIterableAssert.html#extracting
AbstractIterableAssert.html#containsExactlyElementsOf

塔吉尔·瓦列夫(Tagir Valeev)

在Java-8类型中,比在以前的Java版本中进行推理更棘手。特别是,现在表达式的类型可能取决于周围的上下文,而不仅取决于表达式本身。当你写

ListAssert<? extends Class<? extends Number>> implicitLambda = assertThat(actual).extracting(t -> t.getClass());

您提供了这样的上下文。您还可以将此表达式分配给其他类型:

ListAssert<Class<?>> implicitLambda2 = assertThat(actual).extracting(t -> t.getClass());

这也有效。请注意,您无法分配implicitLambdaimplicitLambda2您都不能分配implicitLambda2implicitLambda这两种类型无关。因此事实是:表达式本身可能没有特定的类型,它仅具有一组约束,这些约束可以根据周围的上下文来解决。通常,在将表达式分配,强制转换或传递给另一个方法时,将发生约束解析。JLS第18章对此进行了介绍,尽管很难阅读。

在链接调用中,没有合适的周围环境来明确地解析约束,因此,可能以与链中的下一个调用不兼容的方式解析类型(从不考虑链接调用来绑定约束)。您已经找到两种消除歧义的方法。一种是使用方法参考。这会有所帮助,因为对函数接口(由JLS 15.13.2覆盖)的映射方法引用与将lambda映射到函数接口(由JLS 15.27.3覆盖)完全不同在这里,它有助于设置更具体的约束。另一个是明确指定lambda参数。JLS 15.27.3中的以下语句涵盖了这一点:

如果lambda表达式是显式键入的,则其形式参数类型与函数类型的参数类型相同。

因此,此处执行了更简单的类型解析过程。还有另一种方法:指定显式泛型参数:

// compiles fine
assertThat(actual).<Class<? extends Number>>extracting(t -> t.getClass()).containsExactlyElementsOf(expected);
// also compiles
assertThat(actual).<Class<?>>extracting(t -> t.getClass()).containsExactlyElementsOf(expected);

有时这是最短的方法。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用静态导入编译运行时参数注释时出现“不兼容类型”错误

来自分类Dev

使用FirebaseMessagingService类时出现错误“返回类型int与Intent不兼容”

来自分类Dev

使用别名时无法隐式转换类型错误

来自分类Dev

使用别名时无法隐式转换类型错误

来自分类Dev

使用d3.mouse时出现D3打字稿错误:“ this”隐式具有类型“ any”,因为它没有类型注释

来自分类Dev

在Apache服务器中设置指令时出现不兼容的指针类型错误

来自分类Dev

覆盖类型界限时出现不兼容的类型错误

来自分类Dev

使用 EF6 存储数据时出现“不允许从数据类型 nvarchar(max) 隐式转换为 varbinary”错误

来自分类Dev

使用指针时不兼容的类型

来自分类Dev

使用指针时不兼容的类型

来自分类Dev

在Android Studio中出现vitamio错误。不兼容的类型

来自分类Dev

错误:初始化类型时类型不兼容

来自分类Dev

当我混合使用隐式,类型参数和Nothing时发生编译错误

来自分类Dev

使用pyinstaller转换python脚本时出现问题。导入错误:库不兼容

来自分类Dev

现在在使用if else语句时出现不兼容错误

来自分类Dev

尝试实现`Absurd`类型类时的隐式错误

来自分类Dev

查看表数据时出现不兼容错误消息

来自分类Dev

为什么会出现错误“从'NSArray *'分配给'NSMutableArray *'的指针类型不兼容”。在排序键时?

来自分类Dev

“仅参数值大于某个特定数字时”出现“不兼容类型作为参数传递”错误

来自分类Dev

为什么会出现错误“从'NSArray *'分配给'NSMutableArray *'的指针类型不兼容”。在排序键时?

来自分类Dev

错误:使用类型'taus88_t'|初始化类型'struct taus88_t *'时类型不兼容?

来自分类Dev

地图不兼容的类型错误

来自分类Dev

AlertDialog不兼容的类型错误

来自分类Dev

Greenfoot不兼容的类型错误

来自分类Dev

搜索隐式转换时,Scala是否使用目标类型?

来自分类Dev

在Spring MVC中对@RequestBody使用通用类型时出现“参数类型不匹配”错误

来自分类Dev

Coq:“隐式”后预期出现语法错误“类型”或“类型”

来自分类Dev

当似乎不涉及“ long”类型时,无法将“ long”类型隐式转换为“ int”

来自分类Dev

隐式使用结构类型

Related 相关文章

  1. 1

    使用静态导入编译运行时参数注释时出现“不兼容类型”错误

  2. 2

    使用FirebaseMessagingService类时出现错误“返回类型int与Intent不兼容”

  3. 3

    使用别名时无法隐式转换类型错误

  4. 4

    使用别名时无法隐式转换类型错误

  5. 5

    使用d3.mouse时出现D3打字稿错误:“ this”隐式具有类型“ any”,因为它没有类型注释

  6. 6

    在Apache服务器中设置指令时出现不兼容的指针类型错误

  7. 7

    覆盖类型界限时出现不兼容的类型错误

  8. 8

    使用 EF6 存储数据时出现“不允许从数据类型 nvarchar(max) 隐式转换为 varbinary”错误

  9. 9

    使用指针时不兼容的类型

  10. 10

    使用指针时不兼容的类型

  11. 11

    在Android Studio中出现vitamio错误。不兼容的类型

  12. 12

    错误:初始化类型时类型不兼容

  13. 13

    当我混合使用隐式,类型参数和Nothing时发生编译错误

  14. 14

    使用pyinstaller转换python脚本时出现问题。导入错误:库不兼容

  15. 15

    现在在使用if else语句时出现不兼容错误

  16. 16

    尝试实现`Absurd`类型类时的隐式错误

  17. 17

    查看表数据时出现不兼容错误消息

  18. 18

    为什么会出现错误“从'NSArray *'分配给'NSMutableArray *'的指针类型不兼容”。在排序键时?

  19. 19

    “仅参数值大于某个特定数字时”出现“不兼容类型作为参数传递”错误

  20. 20

    为什么会出现错误“从'NSArray *'分配给'NSMutableArray *'的指针类型不兼容”。在排序键时?

  21. 21

    错误:使用类型'taus88_t'|初始化类型'struct taus88_t *'时类型不兼容?

  22. 22

    地图不兼容的类型错误

  23. 23

    AlertDialog不兼容的类型错误

  24. 24

    Greenfoot不兼容的类型错误

  25. 25

    搜索隐式转换时,Scala是否使用目标类型?

  26. 26

    在Spring MVC中对@RequestBody使用通用类型时出现“参数类型不匹配”错误

  27. 27

    Coq:“隐式”后预期出现语法错误“类型”或“类型”

  28. 28

    当似乎不涉及“ long”类型时,无法将“ long”类型隐式转换为“ int”

  29. 29

    隐式使用结构类型

热门标签

归档