我正在做Java课堂练习。我的这段代码包含一个重载的方法:
class A {
// Overloaded method
public void f(int n, float x) {
System.out.println("f(int n, float x) n = " + n + " x = " + x);
}
private void f(long q, double y) {
System.out.println("f(long q, double y) q = " + q + " y = " + y);
}
public void f(double y1, double y2) {
System.out.println("f(double y1, double y2) y1 = " + y1 + " y2 = " + y2);
}
public void g() {
int n = 1;
long q = 12;
float x = 1.5f;
double y = 2.5;
System.out.println("--- dans g ");
f(n, q);
f(q, n);
f(n, x);
f(n, y);
}
}
主要:
public static void main(String[] args){
A a = new A() ;
a.g() ;
System.out.println ("--- dans main") ;
int n=1 ;
long q=12 ;
float x=1.5f ;
double y = 2.5 ;
a.f(n, q) ; // my problem is here
a.f(q, n) ;
a.f(n, x) ;
a.f(n, y) ;
}
当我在main中调用方法a.f(n,q)
时,我会期望一个错误,但是当我的f(int n, float x)
是一个q
且大小较大时,它会调用方法long
那么float
的大小(8字节/ 4字节)那么我想知道这些原始类型如何工作?
答案 0 :(得分:7)
Method invocations占据了规范的相当大的一部分。总而言之,编译器进行如下操作:
步骤2是这里最有趣的步骤:此过程分为多个步骤。总结一下:
您提供的参数与重载的任何参数类型都不完全匹配,因此您需要检查是否可以转换该参数以允许严格调用。严格调用are中的转换:
- 身份转换(第5.1.1节)
- 不断扩大的原始转换(第5.1.2节)
- 扩展的参考转换(第5.1.5节)
int
可以通过身份转换转换为int
。 widening primitive conversion可以将long
转换为float
。
因此f(int, float)
适用。
f(long, double)
和f(double, double)
也适用,因为int
可以扩展为long
和double
;和long
可以扩展为double
。
但是,由于f(int, float)
可以扩展为int
和long
,而double
可以扩展为{{ 1}}。因此,通过informal intuition laid out in JLS Sec 15.12.2.5,这些方法不如float
特有。因此,double
是被调用的那个。
答案 1 :(得分:1)
longs
可以转换为float
而不会引起错误。但是,你可能会失去精度。
有关详细信息,请参见the specs。
答案 2 :(得分:-2)
以下19种特定于原始类型的转换称为扩大原始转换:
字节为短,整数,长,浮点或双精度
short到int,long,float或double
char转换为int,long,float或double
int表示long,float或double
漂浮或翻倍的长度
浮动翻倍
简化原始转换不会丢失有关数值的整体大小的信息。
...
将int或long值转换为float或将long值转换为double可能会导致精度损失-也就是说,结果可能会丢失该值的某些最低有效位。在这种情况下,最终的浮点值将是long值的正确舍入版本。