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

泛型类型推理不使用方法链接?

汪茂
2023-03-14

此代码在Java 8中编译,但在Java 7中编译失败:

class Map<K,V> {
    static <K,V> Map<K,V> empty() {return null;}
    Map<K,V> put(K k, V v) {return null;}
    V get(K k) {return null;}
}

class A {
    static void f(Map<Integer,String> m){}
    public static void main(String[] args) {
        f(Map.empty());
    }
}

它不能推断从映射返回的映射的具体类型。空():

$ javac7 A.java
A.java:10: error: method f in class A cannot be applied to given types;
        f(Map.empty());
        ^
  required: Map<Integer,String>
  found: Map<Object,Object>
  reason: actual argument Map<Object,Object> cannot be converted to Map<Integer,String> by method invocation conversion
1 error

如果将调用更改为f(Map),则会编译。

但是如果您将调用更改为f(Map.empty())。放(1,“A”)。put(2,“B”)) ,它无法在Java 7和8上再次编译。为什么?

$ $javac7 A.java 
A.java:10: error: method f in class A cannot be applied to given types;
        f(Map.empty().put(1,"A").put(2,"B"));
        ^
  required: Map<Integer,String>
  found: Map<Object,Object>
  reason: actual argument Map<Object,Object> cannot be converted to Map<Integer,String> by method invocation conversion
1 error

$ $javac8 A.java
A.java:10: error: incompatible types: Map<Object,Object> cannot be converted to Map<Integer,String>
        f(Map.empty().put(1,"A").put(2,"B"));
                                    ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error

$ $javac8 -Xdiags:verbose A.java
A.java:10: error: method f in class A cannot be applied to given types;
        f(Map.empty().put(1,"A").put(2,"B"));
        ^
  required: Map<Integer,String>
  found: Map<Object,Object>
  reason: argument mismatch; Map<Object,Object> cannot be converted to Map<Integer,String>
1 error

共有2个答案

萧琛
2023-03-14

地图的类型是什么。进入comparingByValue()。反转()?-只是为了更简单地回答这个问题。

unSortedMap.entrySet().stream()
                    .filter(e -> e.getValue() > 1)
                    .sorted(Entry.comparingByValue(Comparator.reverseOrder()))
                    .collect(Collectors.toMap(Entry::getKey, Entry::getValue,
                            (e1, e2) -> e1, LinkedHashMap::new));
晋奕
2023-03-14

为什么?

因为泛型类型的类型推断还没有扩展到链式调用。

来自泛型类型推断的java教程:

什么是目标类型的概念已经扩展到包括方法参数。

这就是为什么这段代码:

f(Map.empty());

编译。

但这段代码没有,因为这是一个链式调用:

f(Map.empty().put(1,"A").put(2,"B"));

您还可以在JavaTM编程语言最终版本的JSR-000335 Lambda表达式中找到一小段内容进行评估(特别是第D部分):

在a()中,允许推理“连锁”有一些兴趣。b(),将类型信息从b的调用传递到a的调用。这又增加了推理算法的复杂性,因为部分信息必须双向传递;只有在所有实例化(例如List)的a()返回类型的擦除都已修复时,它才起作用。由于目标类型不容易派生,因此此功能不太适合多边形表达式模型;但是,也许通过进一步的增强,将来可以添加它。

所以可能在Java 9中。

 类似资料:
  • 我得到了一个编译错误,我不明白原因。 我正在尝试创建一个扩展另一个生成器的生成器,所有这些生成器都使用泛型类型。 问题是一些泛型方法的返回类型是父类,而不是子类,这就阻止了我链接任何子方法。 下面是一个简单的例子: 为什么会出现编译错误?我怎样才能使它按预期工作? 编辑: 由于下面的答案,我通过以下两个更改成功地解决了这个问题 1-我将BuilderChildStatic类generic更改为正常

  • 如果我有类和collection并尝试将它们传递给方法,但不断得到编译时异常。我试过通配符捕获和其他方法,但没有运气。我一定是错过了一些明显的东西。欢迎任何建议。 更新:有人将此标记为与其他泛型通配符相关的问题重复。然而,这是非常不同的情况。我们拥有的是 其中params、clz和items基于相同的类型t,当我们只有一个参数时,可以使用通配符捕获方法。但这里有通配符变量和: 它们与和具有类似的关

  • 问题内容: 没有静态成员可以使用类型参数,但是可以使用泛型类型参数调用静态成员吗​​?例如:- 这里的add()是一个静态方法。 在类似的主题上也有一些C#问题和答案,但是我不太确定如何在Java中使用它。 问题答案: 不,如果A是泛型类型,则无法执行。(Bozho对fast的回答是:),可能认为A是具体类型。 可行的方法如下。 但这可能不是您想要的。 阅读您的评论后,听起来您真正想要做的是: 您

  • 问题内容: 如果在Java中创建泛型类(该类具有泛型类型参数),则可以使用泛型方法(该方法带有泛型类型参数)吗? 考虑以下示例: 正如您对通用方法所期望的那样,我可以使用任何对象调用的实例: 但是,如果我尝试使用 不 指定泛型类型的实例,则无论传入什么,我都会调用返回, 奇怪的是,如果返回类型是通用类,它将编译(例如(实际上,这可以解释-参见下面的答案)): 此外,如果输入通用类,即使仅使用通配符

  • 如果在Java中创建泛型类(该类具有泛型类型参数),是否可以使用泛型方法(该方法采用泛型类型参数)? 考虑下面的例子: 正如您所期望的那样,对于任何对象,的实例,我都可以调用: 但是,如果我试图使用的实例而不指定泛型类型,那么调用将返回一个

  • 编译时,此代码将产生以下+错误: 问题是访问中的类型T与列表中的T不相同。如何修复此编译问题?