参数中的Java类型提升
我偶然发现了这个片段:
public class ParamTest {
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
}
public static void printSum(long a, long b) {
System.out.println("In long " + (a + b));
}
public static void printSum(double a, long b) {
System.out.println("In doubleLONG " + (a + b));
}
public static void main(String[] args) {
printSum(1, 2);
}
}
这将导致编译错误:
Error:(15, 9) java: reference to printSum is ambiguous both method printSum(int,double) in ParamTest and method printSum(long,long) in ParamTest match
这怎么会模棱两可呢?在这种情况下,不应该只提升第二个参数,因为第一个参数已经是int了吗?在这种情况下,第一个参数不需要升级,对吗
如果我更新代码以添加其他方法,编译将成功:
public static void printSum(int a, long b) {
System.out.println(String.format("%s, %s ", a, b));
}
让我进一步说明一下。以下代码导致歧义:
public class ParamTest {
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
}
public static void printSum(long a, long b) {
System.out.println("In long " + (a + b));
}
public static void main(String[] args) {
printSum(1, 2);
}
}
那么下面的代码也会导致歧义:
public class ParamTest {
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
}
public static void printSum(double a, long b) {
System.out.println("In doubleLONG " + (a + b));
}
public static void main(String[] args) {
printSum(1, 2);
}
}
但是,此不会导致歧义:
public class ParamTest {
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
}
public static void printSum(long a, double b) {
System.out.println("In longDBL " + (a + b));
}
public static void main(String[] args) {
printSum(1, 2);
}
}
# 1 楼答案
这的确是一个非常有趣的问题。让我们一步一步地浏览Java语言规范
当编译器试图识别可能适用的方法时,它要做的第一件事就是serching for methods applicable by Strict Invocation
在您的情况下,没有这样的方法,因此下一步是find methods applicable by Loose Invocation
此时,所有方法都匹配,因此在松散调用适用的方法中选择最具体的方法(§15.12.2.5)
这是一个关键时刻,让我们仔细看看
(我们只对以下案例感兴趣):
简单地说,如果方法的所有参数类型都更具体,则方法更具体。及
表达式
S <: T
表示S
是T
的一个亚型。对于基本体,我们有以下关系:让我们看看你的方法,看看哪一个比其他方法更具体
在本例中,方法1的第一个参数明显比方法2的第一个参数更具体(如果使用整数值调用它们:
printSum(1, 2)
)但是第二个参数对于方法2更具体,因为long < double
。因此,这些方法中没有一种比另一种更具体。这就是为什么你在这里有歧义在以下示例中:
方法1的第一个参数类型比方法2中的参数类型更具体,因为
int < long
和第二个参数类型对它们都是相同的,这就是选择方法1的原因# 2 楼答案
我认为这与JLS关于15.12.2.5. Choosing the Most Specific Method的特定规则有关。它指出:
Java如何选择最具体的方法,本文将进一步解释:
在您的示例中,所有方法都是可访问的,并且适用于方法调用,因此,Java需要确定其中哪一个是最具体的
对于这些方法,没有一种更具体:
第四种方法精确地清除歧义,因为它满足了最具体的必要条件
也就是说,(int,long)可以传递给(int,double),(long,long)或(double,long),而不会出现编译错误
# 3 楼答案
因为int值在java中也可以被视为double。意味着
double a = 3
是有效的,并且与长long b = 3
相同,所以这就是为什么它会产生歧义。 你打电话对于这三种方法来说都很混乱,因为这三种方法都是有效的:
您可以将L放在末尾,以指定它的长值。例如:
对于double,您需要将其转换为:
也请阅读@Erwin Bolwidt的评论