Java方法重载场景下byte为何未被类型提升为long
Java重载构造方法匹配歧义问题原因解析
这个现象完全符合Java语言规范中定义的重载方法匹配优先级规则,核心逻辑如下:
基础规则说明
Java重载方法的匹配分为三个阶段,只有前一阶段找不到匹配方法才会进入下一阶段:
- 第一阶段:仅允许基础类型加宽转换,不允许自动拆装箱、可变参数匹配,我们遇到的这个场景就属于这一阶段的匹配
- 第二阶段:允许加宽转换+自动拆装箱
- 第三阶段:允许加宽+拆装箱+可变参数
第一阶段选择最具体方法的核心规则是:
方法A比方法B更具体的前提是:对于每一个参数位置,方法A的形参类型都比方法B的对应形参类型,更接近实参的原始类型(即实参转换到A的形参的路径更短)。如果没有任何一个方法比其他所有可行方法都更具体,就会抛出匹配歧义错误。
基础类型加宽的优先级顺序(从近到远):byte→short→int→long→float→double,越靠前的类型和byte的匹配度越高。
第一段代码匹配逻辑说明
第一段代码的三个构造方法为:
- 构造1:
Test(int, byte) - 构造2:
Test(int, float) - 构造3:
Test(float, int)
实参为两个byte类型(byte b1, byte b2): - 构造1的第一个参数:
byte可以1步加宽为int,第二个参数完全匹配不需要转换,整体匹配度最高 - 剩下两个构造都需要对两个参数各做一次加宽转换,匹配度低于构造1
所以编译器直接选中构造1,没有歧义。
第二段代码歧义原因说明
修改后三个构造方法为:
- 构造1:
Test(long, byte) - 构造2:
Test(int, float) - 构造3:
Test(float, int)
同样传入(b1, b2)两个byte参数:
步骤1:筛选可行方法
三个方法都满足「所有参数都可以通过加宽转换得到」的要求,都是可行方法。
步骤2:淘汰匹配度更低的构造1
对比构造1和构造2:
- 第一个参数:构造2的
int比构造1的long更接近byte(int在加宽优先级里排在long前面),构造2占优 - 第二个参数:构造1的
byte比构造2的float更接近byte,构造1占优
两者都没有完全优于对方,但是构造1的第一个参数匹配度弱于构造2,且不存在构造1所有参数都比其他两个构造更优的情况,因此构造1会被先排除出最优候选列表。
步骤3:剩余两个构造出现歧义
剩下构造2(int, float)和构造3(float, int):
- 构造2的第一个参数
int比构造3的float更接近byte,构造2占优 - 构造3的第二个参数
int比构造2的float更接近byte,构造3占优
两个构造都没有比对方更具体,编译器无法选出唯一匹配的方法,因此抛出构造方法引用歧义错误。
内容的提问来源于stack exchange,提问作者Prajwal Ramesh
相关产品推荐
相关产品推荐

