我有方法重载,例如:
public int sum1(int a, int b)
{
int c= a+b;
System.out.println("The method1");
return c;
}
public float sum1(int a, float b)
{
float c= a+b;
System.out.println("The method2");
return c;
}
public double sum1(float a, float b)
{
double c= (double) a+b;
System.out.println("The method3");
return c;
}
从 main 方法,假设我们有
double x=10.10f;
double y=10.20f;
x 和 y 的表面类型是 double,但实际类型是 float。当我打电话时
System.out.println(" the output is :"+cc.sum1(x,y));
编译时的错误。
The method sum1(int, int) in the type Class is not applicable for the arguments double, double).
它应该通过将 double 转换为 float 去到 sum1(即 method3)的地方
最佳答案
这个答案的 TL;DR 版本:
- 基本类型的变量在执行时和编译时永远不会有不同的类型。 (
double
始终是double
,永远不会是float
,等等) - 重载解析(选择使用哪个方法签名)是使用表达式的编译时类型执行的
- 使用方法调用目标的执行时类型执行所选签名的方法实现
the apparent type for x and y is double, but the actual type is float
不,不是。您刚刚获得了从分配的 float
文字到 double
值的转换。 实际值是double
。
基元不像对象那样工作 - 例如,不知道 int
值仍然是 double
变量中的 int
.
以整数类型为例更简单。假设我们有:
byte b = 100;
int x = b;
x
的值是表示值 100 的 32 位整数。它“不知道”它最初是从 byte
值分配的。 . 刚好在赋值点发生了从 byte
到 int
的转换。
将其与引用 类型进行比较:
String x = "hello";
Object y = x;
这里,y
的值实际上是对String
对象的引用。该类型信息之所以得以保留,正是因为有一个完整的对象可以包含它,并且因为变量本身的值只是一个引用。 (这些位本身不需要作为分配的一部分进行更改 - 至少在一个简单的 VM 中,它们将与 x
和 y
中的位完全相同,因为他们指的是同一个对象。)
但是,即使在那种情况下,重载解析也会根据参数的编译时 类型发生,而不是它们在执行时的实际值。涉及变量的执行时类型的唯一方法是根据方法调用的目标覆盖。所以如果我们有:
Foo f = new X();
Foo g = new Y();
Foo h = new Z();
f.someMethod(g, h);
... 然后编译器将在 Foo
中寻找一个方法,它有两个 Foo
参数(或 Object
或其他父类(super class)/接口(interface)) - 所涉及对象的实际类型无关紧要。但是,在执行时,如果该方法已在 X
中被覆盖,则由于对象 f
的值引用的执行时类型,将调用该覆盖到。
关于方法重载中的 Java 转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27499522/