这一节的内容都是的干货!!!
不同数据类型的转换主要分为:
小类型转为大类型
大类型转为小类型
注意事项:
只有相同数据类型之间可以转换,数值型之间的转换
接下来就各个类型之间的转换做一个详细的介绍
int 和 long之间的转换:
int a = 10;
//隐式类型转换
//把int转为long
long b = 20;
a = b;//编译不通过
b = a;//编译通过
a = b执行报错的原因:
a是一个整型,b是long类型,把一个long类型的变量赋值给int类型可能会出现整型溢出的问题
int a = Integer.MAX_VALUE;
long b = a + 1
//执行结果 b = -2147483648
程序的执行都是从右向左执行的,先执行a+1,这个时候时int+int,得到的结果还是int,然后赋值给long,也就是将溢出后的结果赋值给b
总的来说,先计算后赋值,这与计算的优先级有关
小类型转为大类型,是自动提升的:
- 小类型的变量值赋值给大类型时
long b = 20;
- 小类型和大类型进行数学运算时,首先会将小类型提升为大类型后再进行数学运算
int a = 10;
long b = a + 1L;
这里会先把a提升为long类型
大类型转为小类型需要强制类型转换,但有可能会丢失精度(数据溢出或者数据部分丢失)
比如long -> int的时候,需要强制类型转换:
int a = 1;
double b = 2;
System.out.println(a / b);
//执行结果 0.5
这里发生了两次类型提升:
double b = 2;
首先是这里的2为字面常量,默认为int型,由于double类型比int类型大,因此赋值的时候提升为double型
System.out.println(a / b);
其次,a是int型,b是double型,两者进行数学运算的时候,int型先提升为double型,然后在进行计算,最终得到的结果也是double型
强制类型转换,丢失精度:
int a = 1;
double b = 2;
double c = a / b;
System.out.println((int)c);
//执行结果为 0
这里c的值是0.5,把c强制类型转换为int型的时候,把小数舍弃了,这就精度丢失
int 和 byte/short之间的转换:
代码1:
int a = 100;
byte b = (byte)a;//大到小,强制类型提升
int c = b;//小到大,自动提升
上面所讲的 int 与 long 之间的转换同样适用于int 与 byte之间的转换
但是也有特殊点,看下面一段代码:
代码2:
byte b = 120;//编译成功
byte b = 130;//编译失败
byte b = (byte)130;//编译成功
如果根据整型字面量来说,120默认是int型,赋值给小类型byte时应该强制类型转换,那为什么直接赋值120也能通过编译呢?
其次,既然120能成功赋值,为什么130又不行了呢?
其原因在于:
由于CPU读写数据时,都是以4字节为单位进行读取和写入的,因此对于数值型和字符型来说,小于4字节的数据类型,在存储时会转为4字节,即byte类型在保存时会转为int类型
当把byte类型取值范围之内的整数赋值给byte时,因为byte类型最终要转为int类型,所以可以直接赋值,但是超出byte的范围时,仍然需要强制类型转换
代码3:
int a = 100;
byte b = a;
//编译无法通过
当把一个int变量而不是字面量赋值给byte时,无论是否超出保存范围,都需要强转
代码4:
byte a = 10;
byte b = 20;
byte c = (byte)(a + b);
System.out.println(c);
//执行结果 30
在计算机底层,byte在存储的时候会转为int,计算两个byte型相加时,因为已经转为int型,所以依然要强转为byte型
代码5:
final byte a = 10;
final byte b = 20;
byte c = a + b;
System.out.println(c);
//执行结果 30
被final修饰的变量,除了数据值不能改,类型也不能提升
因此常量存储时,仍然是byte类型!!!
int和char之间的相互转换
计算机的内部都是0和1,char类型在存储的时候是按照Unicode编码规则转为int存储
代码1:
public class Test {
public static void main(String[] args) {
char a = 'a';
int b = a;
char c = 'A';
int d = c;
System.out.println(b);//执行结果 97
System.out.println(d);//执行结果 65
}
}
char -> int 是自动提升的,按照unicode编码将字符‘a’转为int型
所谓的unicode编码,就是把不同的文字和符号按照一定的规则转为数字而已
代码2:
int a = 97;
char b = (char)a;
System.out.println(b);//执行结果 'a'
int -> char 属于大类型转小类型,因此需要强制类型转换
不同的字符在Java中都能转换为一一对应的数字
字符和整型之间的相互转换是非常重要且常用的!!
int和String之间的转换
- int -> String的两种办法:
1- 直接使用String对象 + 的方式
2- 使用String的valueOf方法
public class Test {
public static void main(String[] args) {
int num = 10;
String str1 = "" + num;//任意字符串和其他类型"+",都会把其他类型转为字符串
String str2 = String.valueOf(num);//利用valueof将int -> String
System.out.println(str1);//执行结果 10
System.out.println(str2);//执行结果 10
}
}
- String -> int
如果我们要把String转为int,需要调用int包装类Integer.parselnt( )
String str1 = "123";//纯数字组成的字符串
String str2 = "123abc";//不是有纯数字组成的字符串
//把str1这个字符串变量转为int型
int a = Integer.parseInt(str1);//执行结果 123
//把str2这个字符串变量转为int型
int a = Integer.parseInt(str2);//编译失败
如果字符串为都是由数字组成的时候,可以直接使用
但是字符串中包含了非数字,调用这个方法时就会报错
数据类型的默认值
在Java中所有数据类型都有默认值,定义后没有赋值,会有默认值(但只存在于类变量中,方法中的局部变量不存在默认值)
数值型的默认值是0
浮点型的默认值是0.0
char的默认值是‘\u0000’ - 相当于占位符
boolean的默认值是false
String的默认值是null
代码1:
public class Test {
public static void main(String[] args) {
int a;
System.out.println(a);
}
}//编译报错:java: 可能尚未初始化变量a
代码2:
public class Test {
int a;
double b;
char c;
boolean d;
String str;
public static void main(String[] args) {
System.out.println(new Test().a);
System.out.println(new Test().b);
System.out.println(new Test().c);
System.out.println(new Test().d);
System.out.println(new Test().str);
}
}
执行结果如下:
可见在类中定义的变量即是没有赋值也有默认值,而方法中的局部变量必须要初始化才能使用
互不相关的两种类型不能转换的!!
public class Test {
public static void main(String[] args) {
boolean a = (boolean)1;//编译不通过
boolena b = true;
int c = (int)b;//编译不通过
}
}