import java.util.function.*;

class Test { 
    void test(int    foo,Consumer<Integer> bar) { }
    void test(long   foo,Consumer<Long>    bar) { }
    void test(float  foo,Consumer<Float>   bar) { }
    void test(double foo,Consumer<Double>  bar) { }
}

当我用javac -Xlint Test.java编译它时,我得到了几个警告:

Test.java:4: warning: [overloads] test(int,Consumer<Integer>) in Test is potentially ambiguous with test(long,Consumer<Long>) in Test
    void test(int    foo,Consumer<Integer> bar) { }
         ^
Test.java:6: warning: [overloads] test(float,Consumer<Float>) in Test is potentially ambiguous with test(double,Consumer<Double>) in Test
    void test(float  foo,Consumer<Float>   bar) { }
         ^
2 warnings

如果我将Consumer改为supplier,警告消失.这个程序是免费的:

import java.util.function.*;

class Test { 
    void test(int    foo,supplier<Integer> bar) { }
    void test(long   foo,supplier<Long>    bar) { }
    void test(float  foo,supplier<Float>   bar) { }
    void test(double foo,supplier<Double>  bar) { }
}

这是为什么?这个警告是什么意思?这些方法如何模糊?抑制警告是否安全?

解决方法

这些警告是由于重载分辨率,目标打字和类型推断之间有趣的交集而发生的.编译器为您提前思考,并且警告您,因为大多数lambdas都没有明确声明的类型.例如,考虑这个电话:
test(1,i -> { });

我的类型是什么?编译器在完成重载分辨率之前无法推断出这一点,但值1匹配所有四个重载.无论选择哪个超负荷都会影响第二个参数的目标类型,这反过来将影响为i推断的类型.这里真的没有足够的信息来编译器来决定要调用哪个方法,所以这一行实际上会导致编译时错误:

error: reference to test is ambiguous
           both method test(float,Consumer<Float>) in Test and
           method test(double,Consumer<Double>) in Test match

(有趣的是,它提到了float和double重载,但是如果你对其中的一个发表评论,你会得到相同的长时间重载错误.)

可以想象一个策略,编译器使用最具体的规则完成重载解析,从而选择使用int arg的重载.那么它将有一个明确的目标类型来应用于lambda.编译器设计者觉得这太微妙了,而且有些情况下程序员会惊讶于哪个重载最终被调用.而不是以可能的意想不到的方式编译程序,他们认为使这个错误更加安全,并强制程序员消除歧义.

编译器在方法声明中发出警告,以指示程序员可能编写的代码来调用其中一个方法(如上所示)将导致编译时错误.

要消除这个电话的歧义,只好写一个

test(1,(Integer i) -> { });

或者为i参数声明一些其他显式类型.另一种方法是在lambda之前添加一个cast:

test(1,(Consumer<Integer>)i -> { });

但这可以说更糟.您可能不希望您的API的呼叫者必须在每个呼叫点与这种事情搏斗.

供应商案例不会出现这些警告,因为供应商的类型可以通过本地推理来确定,而不需要任何类型的推断.

你可能想要重新思考将这个API放在一起的方式.如果您真的想要使用这些参数类型的方法,那么可以重命名方法testInt,testLong等,并避免完全重载.请注意,在类似的情况下,Java SE API已经做到了这一点,比如比较比较,比较长和比较比较比较;还可以在Stream上映射ToInt,mapToLong和mapTodouble.

java – 警告:[overloads]方法m1与方法m2有潜在的不确定性的更多相关文章

  1. 用swift实现navigation bar的完全透明 &amp; navigation bar中button的字体大小调整

    2>或者我们可以来改变这个返回按钮的样式,比如手动把它的文字字体大小调整下注意,因为我们其实是改变的UIBarButtonItem,所以,这段代码我们要放到Appdelegate中来实现。这样,所有的bar中的button类的字体都被强制设定为12号大小了

  2. swift – 如何解开任意类型的可选值?

    给定一个[Any]的数组,其中包含可选值和非可选值,例如:我们如何提取在Any类型(如果有)的Optional的值,所以我们可以创建一个通用打印函数,只打印出值。这个printArray函数遍历并打印每个元素:其中将输出:我们如何更改它,以便它只打印底层值,以便它解包的值,如果它是可选的?将总是解包任何类型。

  3. swift – 从常规方法调用协议默认实现

    我想知道是否可能实现这样的事情。它在某种程度上类似于调用super。类中的方法来满足实现每个属性的需求等,但是我看不到使用struct实现相同的可能性。我不知道你是否仍然在寻找这个答案,但方法是从协议定义中删除该函数,将对象转换为Foo,然后调用它的方法:由于某种原因,它只有在函数未声明为协议的一部分,而是在协议的扩展中定义时才有效。

  4. swift – 使用依赖于其他实例变量的值初始化惰性实例变量

    我已经例如尝试将getEventCalendar从方法转换为函数,但这也无济于事.你可以使用一次只执行的闭包来捕获self的属性并在执行时使用它们.例如.W.r.t.对于你自己的尝试:你可以以同样的方式在这个曾经执行过的闭包中使用self的帮助(实例)函数.

  5. 泛型 – 如何在Swift的泛型类上实现NSCoding?

    我在Swift中遇到泛型类和NSCoding问题.具体来说,这个示例代码很好地工作:但是,当我尝试相同的代码,并添加一个泛型参数;当我尝试编码对象;我收到一个’无法识别的选择器发送到实例’错误:以下是错误详细信息和堆栈跟踪:当我读到这一点,当类是通用的时,Swift无法调用encodeWithCoder的实现.它是否正确?为了在泛型类上使用NSCoding,我该如何解决这个问题?

  6. 在Swift 3中如何记录函数的闭包参数的参数?

    在Xcode8beta和Swift3中,当您有一个以闭包为参数的方法时,例如:如何记录关闭所需的参数?据我所知,如果您标记它们,您只能记录关闭参数:这是不太理想的:它强制您在调用闭包时使用参数标签,如果有命名冲突,似乎没有办法区分两者.编辑:as@Arnaud指出,您可以使用_来阻止在调用闭包时使用参数标签:事实上,这是Swift3中唯一有效的方法,因为参数标签不再是类型系统的一部分.

  7. 如何以即时模式从其他.swift文件中包含.swift文件?

    具有功能定义bar.swift的文件:一个脚本可以立即运行foo.swift:如何从foo.swift导入bar.swift的foo()函数?我认为现在的答案是你不能分割多个文件的代码,除非你编译代码.使用#!

  8. Swift枚举具有相同值的多个案例

    在C中,你可以使你的枚举有这个在迅速我想做相当的.但编译器抱怨说它不是唯一的.我如何告诉我,我想要两个案例具有相同的价值?我试过了和但它似乎不像我想要的那样工作.我感谢任何帮助.Swift不支持重复的值.如果您不介意,可以使用这样的东西来模拟它.

  9. swift – 有客观原因我不能拥有带元素标签的单元素元组吗?

    在Swift中直到并包括Swift3,我无法创建一个单元素元组,其中元素被命名.所以funcfoo()–>酒吧很好,而funcfoo()–>产生编译错误.但是,我可以想到这种模式的一些可能用途,例如:…这已经作为SwiftEvolution系统的一部分进行了讨论吗?

  10. swift – 多个让一个守卫声明和一个let一样吗?

    这些在Swift3中有所不同.在这种情况下:你说’可选–解开foo吧.如果成功,可选择将taco打包成qux.如果成功继续.其他……

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部