今天突然想起Java的数值类型自动转换,于是做了个测试,设计思路有点沙雕
先看看Java类型自动转换的图
(实线代表无损转换,虚线代表可能有精度损失的转换)
先定义两个变量,byte q; 和 long w;
然后用这两个变量调用包含不同类型参数的方法,看看会发生什么
参照 byte ---> short ---> int ---> long ---> float ---> double ;
(byte ---> short 为 1,byte ---> int 为2;以此类推)
一、一个方法是参数x的类型差两位,参数y的类型差一位。另一个方法是参数x的类型差一位,参数y的类型差两位。
public class Test {
// x参数类型相差两位,y参数类型相差一位
static void typeConversion(int x,float y){
System.out.println("x参数类型相差两位,y参数类型相差一位:int,float");
}
// x参数类型相差一位,y参数类型相差两位
static void typeConversion(short x,double y){
System.out.println("x参数类型相差一位,y参数类型相差两位:short,double");
}
public static void main(String[] args){
byte q = 1;
long w = 4;
typeConversion(q,w);
}
}
想看看到底会执行那个方法,一测试突然发现报错了
报错内容说我的方法模凌两可,猜测是优先度上两个方法是一样的。即(2+1)=(1+2)
把其中一个方法注释掉后,就没报错。
怀着研究到底的心态,于是换了个方式测试
二、一个方法换成两个参数类型都差一位,另一个方法都差两位
public class Test {
// 两个参数类型都相差一位
static void typeConversion(short x,float y){
System.out.println("两个参数类型都相差一位:int,float");
}
// 两个参数类型都相差两位
static void typeConversion(short x,double y){
System.out.println("两个参数类型都相差两位:short,double");
}
public static void main(String[] args){
byte q = 1;
long w = 4;
typeConversion(q,w);
}
}
这次没有报错,执行成功,它选择了近一点的,即(1+1)优于(2+2)
三、一个方法是参数x的类型相同,参数y类型相差一位;另一个方法是参数x类型相同,参数y类型相差两位
public class Test {
// 参数x类型相同,参数y类型相差一位
static void typeConversion(byte x,float y){
System.out.println("参数x类型相同,参数y类型相差一位:byte,float");
}
// 参数x类型相同,参数y类型相差两位
static void typeConversion(byte x,double y){
System.out.println("参数x类型相同,参数y类型相差两位:byte,double");
}
public static void main(String[] args){
byte q = 1;
long w = 4;
typeConversion(q,w);
}
}
这次也没有报错,执行成功,执行了比较相近的那个,即(0+1)优于(0+2)
四、再换个方法试一下,方法一中参数x类型相同,参数y类型相差一位;另一个方法参数x类型相差一位,参数y类型相同
public class Test{
// 参数x类型相同,参数y类型相差一位
static void typeConversion(byte x,float y){
System.out.println("参数x类型相同,参数y类型相差一位:byte,float");
}
// 参数x类型相差一位,参数y类型相同
static void typeConversion(short x,long y){
System.out.println("参数x类型相差一位,参数y类型相同:short,long");
}
public static void main(String[] args){
byte q = 1;
long w = 4;
typeConversion(q,w);
}
}
可以预见,报了方法模凌两可的错,即
说明优先度上是一样的,把其中一个注释掉就可以了
到这里可以发现,通过显式参数调用两个都需要类型转换的同名方法时,若整体转换等级相等时(多个参数调用未验证),程序会报错,报错原因为 Ambiguous method (选择困难症。)
最后,把所有的方法放到一起,看看哪个优先执行,其中
(1)两个参数类型相同的方法
(2)一个参数类型相同,一个参数类型相差一位
(3)一个参数类型相同,一个参数类型相差两位
(4)参数x类型相差一位,参数y类型相差一位
(5)一个参数类型相差一位,一个参数类型相差两位
(6)两个参数类型都相差两位
public class Test {
// (1)两个参数类型都相同
static void typeConversion(byte x,long y){
System.out.println("两个参数类型都相同:byte,long");
}
// (2)参数x类型相同,参数y类型相差一位
static void typeConversion(byte x,float y){
System.out.println("参数x类型相同,参数y类型相差一位:byte,float");
}
// (3)参数x类型相同,参数y类型相差两位
static void typeConversion(byte x,double y){
System.out.println("参数x类型相同,参数y类型相差两位:byte,double");
}
// (4)参数x类型相差一位,参数y类型相差一位
static void typeConversion(short x,float y){
System.out.println("参数x类型相差一位,参数y类型相差一位:short,float");
}
// (5)参数x类型相差一位,参数y类型相差两位
static void typeConversion(short x,double y) {
System.out.println("x参数类型相差一位,y参数类型相差两位:short,double");
}
// (6)两个参数类型都相差两位
static void typeConversion(int x,double y) {
System.out.println("两个参数类型都相差两位:int,double");
}
public static void main(String[] args){
byte q = 1;
long w = 4;
typeConversion(q,w);
}
}
第一次执行,毫无疑问是两个参数类型都相同的方法(1)
把方法(1)注释掉,再执行,毫无疑问执行力方法(2)
再把方法(2)注释掉,令人意外的是,报错了
方法(3)第一个参数类型已经匹配了,没想到优先度跟方法(4)是一样的
猜测一下:只要存在类型转换,均可用以下公式:
可以直接匹配的参数类型记为0,需要向下转换类型时,转换一位记为1,以此类推。
(个人瞎说)先把方法调用优先度记为 pc ,若直接匹配则pc = 0,若需要类型转换,如方法(3),则为pc = (0+2),方法(4),则pc = (1+1),所以方法(3)与方法(4)优先度相同。
把其中一个注释掉后,均可执行
注释掉方法(3):
注释掉方法(4):
把两个方法都注释掉,往下执行,执行了方法(5)
至此,总算理清了今天的想法。