方法重载和原始类型如何工作?
How method-overloading and primitive types works?
我正在做 Java class 练习。我有这段代码,其中包含一个重载方法:
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 字节)所以我想知道这些基本类型是如何工作的?
longs
可以转换为 float
而不会引发错误。但是你可能会失去精度。
详情见the specs。
Method invocations 占据了规范的很大一部分。总而言之,编译器按如下方式进行:
- 确定可能调用该方法的 classes。
- 确定那些 class 可能被调用的方法。
- 如果确定了不止一种方法,请选择最具体的一种。
第 2 步是这里最有趣的一步:它分为多个步骤。总结:
- 如果 class 上有一个具有完全相同参数类型(严格调用)的非可变参数方法,请选择该方法。
- 如果 class 上有一个非可变参数方法,其参数类型可以从实际参数自动转换(松散调用),请选择该方法。
- 如果 class 上有可变参数方法,其参数类型与自动转换相匹配,请选择它。
您提供的参数与重载的任何参数类型都不完全匹配,因此您需要检查是否可以转换该参数以允许严格调用。严格调用中的转换 are:
- an identity conversion (§5.1.1)
- a widening primitive conversion (§5.1.2)
- a widening reference conversion (§5.1.5)
一个int
可以通过身份转换转换为int
。 long
可以通过 widening primitive conversion 转换为 float
.
因此f(int, float)
适用。
f(long, double)
和f(double, double)
也适用,因为int
可以扩大到long
和double
; long
可以扩大到 double
.
但是,这些没有 f(int, float)
具体,因为 int
可以扩大到 long
和 double
,并且 float
可以扩大到double
。因此,根据 informal intuition laid out in JLS Sec 15.12.2.5,这些方法不如 f(int, float)
具体。因此,f(int, float)
是被调用的。
以下 19 种原始类型的特定转换称为扩展原始类型转换:
byte 到 short、int、long、float 或 double
short 到 int、long、float 或 double
char 到 int、long、float 或 double
int 到 long、float 或 double
长到浮动或加倍
浮动到两倍
扩大基元转换不会丢失有关数值总体大小的信息。
...
将 int 或 long 值转换为 float,或将 long 值转换为 double,可能会导致精度损失 - 也就是说,结果可能会丢失该值的一些最低有效位。在这种情况下,生成的浮点值将是 long 值的正确舍入版本。
我正在做 Java class 练习。我有这段代码,其中包含一个重载方法:
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 字节)所以我想知道这些基本类型是如何工作的?
longs
可以转换为 float
而不会引发错误。但是你可能会失去精度。
详情见the specs。
Method invocations 占据了规范的很大一部分。总而言之,编译器按如下方式进行:
- 确定可能调用该方法的 classes。
- 确定那些 class 可能被调用的方法。
- 如果确定了不止一种方法,请选择最具体的一种。
第 2 步是这里最有趣的一步:它分为多个步骤。总结:
- 如果 class 上有一个具有完全相同参数类型(严格调用)的非可变参数方法,请选择该方法。
- 如果 class 上有一个非可变参数方法,其参数类型可以从实际参数自动转换(松散调用),请选择该方法。
- 如果 class 上有可变参数方法,其参数类型与自动转换相匹配,请选择它。
您提供的参数与重载的任何参数类型都不完全匹配,因此您需要检查是否可以转换该参数以允许严格调用。严格调用中的转换 are:
- an identity conversion (§5.1.1)
- a widening primitive conversion (§5.1.2)
- a widening reference conversion (§5.1.5)
一个int
可以通过身份转换转换为int
。 long
可以通过 widening primitive conversion 转换为 float
.
因此f(int, float)
适用。
f(long, double)
和f(double, double)
也适用,因为int
可以扩大到long
和double
; long
可以扩大到 double
.
但是,这些没有 f(int, float)
具体,因为 int
可以扩大到 long
和 double
,并且 float
可以扩大到double
。因此,根据 informal intuition laid out in JLS Sec 15.12.2.5,这些方法不如 f(int, float)
具体。因此,f(int, float)
是被调用的。
以下 19 种原始类型的特定转换称为扩展原始类型转换:
byte 到 short、int、long、float 或 double
short 到 int、long、float 或 double
char 到 int、long、float 或 double
int 到 long、float 或 double
长到浮动或加倍
浮动到两倍
扩大基元转换不会丢失有关数值总体大小的信息。
...
将 int 或 long 值转换为 float,或将 long 值转换为 double,可能会导致精度损失 - 也就是说,结果可能会丢失该值的一些最低有效位。在这种情况下,生成的浮点值将是 long 值的正确舍入版本。