一、Java中的基本数据类型
数值型:
整型: byte 8bits / 1Byte
short 16bit / 2Byte
int 32bit / 4Byte
long 64bit / 8Byte
浮点型: float 32bit / 4Byte
double 64bit / 8Byte
字符型: char 16bit / 2Byte (与c、c++8位不同,采用16位无符号的Unicode编码)
二、赋值表达式中的类型转换
格式:
目的类型 变量 = (目的类型)(表达式、变量、常量)
或 变量 = (目的类型)(表达式、变量、常量)
注意:上述格式的最后一项中若不是表达式,则可以不加括号。
eg1: byte b = 10;
int i = 5;
b = b + i ;
编译报错!
eg2: byte b = 10;
int i = 5;
i = i + b ;
编译通过。
两例的区别在于, 前者使 byte 型为目标类型, int 型为源类型,目标类型范围小于源类型范围( 8bit < 32 bit),不能进行自动转换,需要经过强制类型转换如下:
eg2.1: byte b = 10;
int i = 5;
b =(byte) (b + i) ;
编译通过。
由此得到赋值表达式类型转换的两种情况:
(1)当目标类型范围大于源类型范围时,能进行自动转换,如eg2
(2)当目标类型范围小于源类型范围时,不能进行自动转换,需要进行强制转换或者称为显示转换,如eg2.1
(3)那么,当目标类型范围等于源类型范围呢?
根据一、Java中的基本数据类型,可以得到,要论范围相等的情况,仅有int 与 float 和 long 与 double这两组类型了。我们可以测试如下:
eg3: int i = 10;
float f = 5.5f;
f = i + f;
float f = 5.5f;
f = i + f;
编译通过,输出f得到15.5
eg4: int i = 10;
float f = 5.5f;
i = f + i;
float f = 5.5f;
i = f + i;
编译报错!
eg5: long i = 10;
float f = 5.5f;
i = i + f;
float f = 5.5f;
i = i + f;
编译报错!
eg6: long i = 10;
double f = 5.5f;
i = i + f;
double f = 5.5f;
i = i + f;
编译报错!
eg7: long i = 10;
double f = 5.5f;
f = i+ f;
double f = 5.5f;
f = i+ f;
编译通过。输入f为15.5
由以上各例可以得到,在数据类型提升中,浮点型的优先级高于整型。
综上所述,我们可以定义赋值表达式中的数值型 数据类型转换优先级如下(注意,此优先级为我们自己定义的的,与平常所说的优先级并不相同。):
低---------------------------------------------------高
byte short int long float double
所以可以总结为:
(1)当目标类型优先级大于源类型优先级时,能进行自动转换。
(2)当目标类型优先级小于源类型优先级时,不能进行自动转换,需要进行强制转换或者称为显示转换。
其实非常好理解。对整型而言,一定体积的液体当然要装在容积更大的容器里,否则要进行强制转换;
对浮点型来说,小数和整数进行算数运算时,自然要保留小数点后的数字,所以结果不能是整型。
三、非赋值表达式中的类型转换
非赋值表达式中的类型转换比如下例:
eg8: int i = 5;
byte b = 10;
System.out.println(b+i);
编译通过且输出为15;
eg9: short i = 5;
byte b = 10;
System.out.println(b+i);
编译通过且输出为15;
eg10: int i = 5;
float b = 10.3f;
System.out.println(b+i);
编译通过且输出为15.3;
其实,多进行其他的数据类型转换就可以发现,这里的类型转换是自动的,而且是按照上面我们得到的优先级进行提升,即:
以表达式中出现的优先级最高的数据类型为最终的数据类型。
四、数值型和字符型的数据转换
以下各例均能通过编译,我们主要来看输出结果:
eg11: System.out.println( (int) 'a' ); //输出为97
eg12: System.out.println( (short) 'a' ); //输出为97
eg13: System.out.println( (long) 'a' ); //输出为97
eg14: System.out.println( (byte) 'a' ); //输出为97
eg15: System.out.println( (float) 'a' ); //输出为97.0
eg16: System.out.println( (double) 'a' ); //输出为97.0
容易看出,数值型和字符型的数据转换其实就是ASCII中的字符和它的二进制编号的一一对应。而且,将字符强制转换为整型,可以得到该字符在ASCII表中中的编号。比如,字符'a'在ASCII表中对应的编号为97.
再来:
eg11: System.out.println( (char) '2' ); //输出为2
这句话的意思是,字符'2'在ASCII表中 对应的编号 所对应的字符 为2 .
eg12: System.out.println( (int) '2' ); //输出为50
这句话的意思是,字符'2'在ASCII表中 对应的编号的 为50 .
eg13: System.out.println( (int) 2 ); //输出为2
这句话的意思是,int型数值2(默认整型即为int型)经过强制转换后得到的值为2.
eg14: System.out.println( (char) 2 ); //输出为一个笑脸
相信eg11~13都不难理解,那么eg14是什么情况呢?
再来看一例:
eg15:System.out.println( (char) 50 ); //输出为2
我们发现了,eg12和eg15其实是一对逆转换。所以我们可以得到:
格式形如 (char) 整型 的转换的意思是 :以这个整型数值作为在ASCII表中编号的那个字符
不仅如此,通过下面的例子:
eg16:byte b =50;
System.out.println( (char) b );
eg17:float f =50.3f;
System.out.println( (char) f );
eg18:
System.out.println( (char) 50.9 );
输出均为2(而且这个2是字符'2',而不是数值2)。
最后一例:
eg19: int i = (char ) (50);
System.out.println( i ); // 输出为 50 。
System.out.println( i ); // 输出为 50 。
其实这里,int i = (char)50 其实等价于 int i = '2';
若我们输出如下:
System.out.println(i);
System.out.println((int)i);
System.out.println((char)i);
System.out.println((int)i);
System.out.println((char)i);
则得到: 50
50
2
这便是Java中数值型和字符型间通过ASCII表连接起来的。奇妙关系。
对博主来说,如果编译报错,很可能是 类型忘记加括号了,谨记!
补充:
为什么赋值表达式和非赋值表达式有上述的区别呢。关键是:
在非赋值表达式,如在
byte b= 5;
System.out.println(b +5);
中 b + 5 自动地对b进行了一个提升,所以最后得到的是 int 型的数值,这没有问题。
但是,在赋值表达式
byte b= 5;
b = b +5;
中,b+5 得到了一个int型的数值,而这个int型的变量被赋给了byte型的变量 b ,所以出错。
请继续看:
byte b= 5;
b += 5;
则编译通过。
其间原因在于操作符 += 对数据类型进行了一个自动的提升,但是,这个提升是暂时的。
再看下面一例:
byte b= 10;
b += 0.2;
System.out.println(b);
b += 0.2;
System.out.println(b);
编译通过,但,输出b依然为10。
这就又反映了java是一名强类型的编程语言,即,一旦一个变量定义时声明了数据类型,那么在它的作用范围内,它永远都是这个数据类型了。
补充二:
现在又有一个问题。
既然 常数 5 默认是 int 型的,那为什么 byte b = 5;可以通过编译呢。
可以猜想到,byte b = 5 和 b += 5 类似,都有一个自动转换的过程。
区别在于:
如补充一中的最后一例, += 操作符右边可以是浮点型数值;但是,右边是常量数值的赋值操作符,是区别整型和浮点型的。比如:
byte b = 11.6; //报错
byte b= (byte)11.6; //通过
五、使用二目运算符时数据类型的自动提升
eg:
short a = 50;
short b = 60;
short c = a + b;
short b = 60;
short c = a + b;
编译不通过。
因为:
使用二目运算符的运算中,低于int型的都要先转化成int进行运算,高于int型的要转换位最高的那个类型运算。
需要进行强制转化:
short c = (short)(a + b);//编译通过