当前位置: 首页 > 知识库问答 >
问题:

Java var与推理类型歧义

卢知
2023-03-14
Collectors.groupingBy((String s)->s.toLowerCase(),Collectors.counting());
Collectors.groupingBy((String s)->s.toLowerCase(Locale.ENGLISH),Collectors.counting());
Collectors.groupingBy(String::toLowerCase,Collectors.counting());

当然,如果我给IntelliJ添加更多上下文,比如:

Collector<String,?,Map<String,Long>> c = Collectors.groupingBy(String::toLowerCase,Collectors.counting());

这是正确的,但在Java10 var推断类型上下文中,这是错误的:

var c = Collectors.groupingBy(String::toLowerCase,Collectors.counting());

我理解编译器不能推断counting的输入类型。如果我写:

Collector<String,?,Long> counter = Collectors.counting();
var c = Collectors.groupingBy(String::toLowerCase,counter);
Reference to 'toLowerCase' is ambiguous, both 'toLowerCase(Locale)' and 'toLowerCase()' match

编译器的错误更加不可读(但包含更多关于推理失败原因的提示),如下所示:

Demo.java:31: error: incompatible types: cannot infer type-variable(s) T#1,K,A,D,CAP#1,T#2
        Collectors.groupingBy(String::toLowerCase,Collectors.counting());
                             ^
    (argument mismatch; invalid method reference
      incompatible types: Object cannot be converted to Locale)
  where T#1,K,A,D,T#2 are type-variables:
    T#1 extends Object declared in method <T#1,K,A,D>groupingBy(Function<? super T#1,? extends K>,Collector<? super T#1,A,D>)
    K extends Object declared in method <T#1,K,A,D>groupingBy(Function<? super T#1,? extends K>,Collector<? super T#1,A,D>)
    A extends Object declared in method <T#1,K,A,D>groupingBy(Function<? super T#1,? extends K>,Collector<? super T#1,A,D>)
    D extends Object declared in method <T#1,K,A,D>groupingBy(Function<? super T#1,? extends K>,Collector<? super T#1,A,D>)
    T#2 extends Object declared in method <T#2>counting()
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Object from capture of ?

共有1个答案

章安宜
2023-03-14

这是编译器的“弱点”,至少在这个JEP到位之前是如此。

我在这里已经回答了几乎相同的问题。JDK核心开发人员也给出了另一个答案。

还有一个问题和你很接近。

 类似资料:
  • 我试图扫描JEP-286关于局部类型推断的信息。我看到这只适用于局部变量-理解。因此,这确实有效: 另一方面,我确实看到这并不能编译: 很明显,事实并非如此,因为JEP是这么说的。现在我的问题是: 声明为的公共/受保护成员失败是完全合理的,至少IMO是如此。但是,为什么即使它是,它也不能编译呢?我只能假设您仍然可以通过反射来获取该变量(我无法获取这样的局部字段)……而获取该变量需要进行转换,很可能

  • 因此,我有一些带有这些签名的Java方法(为了简单起见,删除了注释和代码体): 我在Kotlin中有一些代码,它调用了'join'方法: 例如,如果我想用“分隔符”参数调用后一个方法签名,问题就来了: 这段代码无法编译。编译器无法决定调用哪个方法。错误: 错误:(5,13)Kotlin:在未完成类型推断的情况下,无法在以下候选项中进行选择:public open fun join(vararg A

  • 我正在尝试运行以下代码,由于类型推断,它在JDK8下编译得很好: 但是,运行此命令会抛出ClassCastException:CB无法强制转换为[Ljava.lang.Object,但CB b=convert(a)可以正常工作。 知道为什么吗?

  • 问题内容: 我尝试扫描有关本地类型推断的JEP-286。我看到这仅适用于局部变量- 了解。因此这确实有效: 我确实看到,另一方面,它无法编译: 很明显,事实并非如此,因为JEP是这样说的。现在我的问题是: 对于宣布失败的 公共/受保护 成员,至少是IMO,这是完全合理的。但是,为什么即使编译也不编译呢?我只能假设您仍然可以通过反射保留该变量(而我无法获得这样的局部字段)…而且获取该变量可能需要强制

  • 查看我在某处(这里是游乐场)找到的这个Typescript4.2片段: 我的头不能绕着它。TS如何处理这件事?它怎么不卡在无限递归里?具体地说,对于和的情况,悬停在变量上显示TS将类型解析为和。这是怎么回事?

  • 条款二:理解auto类型推导 如果你已经读过Item1的模板类型推导,那么你几乎已经知道了auto类型推导的大部分内容,至于为什么不是全部是因为这里有一个auto不同于模板类型推导的例外。但这怎么可能,模板类型推导包括模板,函数,形参,但是auto不处理这些东西啊。 你是对的,但没关系。auto类型推导和模板类型推导有一个直接的映射关系。它们之间可以通过一个非常规范非常系统化的转换流程来转换彼此。