1. 类型转换是什么
当两个数据类型不同的变量发生值/引用交换的过程,称为类型转换。
2. 类型转换的类型
根据人为干扰的强度分两类:
i. 自动类型转换。
ii. 强制类型转换。
2.1. 自动类型转换
自动类型转换无需程序员作代码上的干预,JVM会自动识别类型并进行类型转换。
2.1.1. 触发情况
i. 容量小的数据类型可以自动转化成容量大的数据类型。
ii. 精度低的数据类型可以自动转化为精度高的数据类型。
iii. 类型相兼容可自动转化(整形和浮点型相兼容、整形和char类型相兼容)。
iv. 子类类型可以自动转化为父类类型(向上造型)。
注意事项:
[1] 数据类型包括包装类型。
[2] boolean类型不能和基本数据类型发生类型转化。
--案例1
public static void main(String[] args) {
// [1] 容量小的数据类型可以自动转化成容量大的数据类型
byte a = 10;
int b = a;
System.out.println("b = " + b);
// [2] 精度低的数据类型可以自动转化为精度高的数据类型
float c = 20f;
double d = c;
System.out.println("d = " + d);
// [3] 类型相兼容
// [3.1] 整形和浮点型
long e = 30L;
double f = e;
System.out.println("f = " + f);
// [3.2] 整形和char类型
char g = 'a';
int h = g;
System.out.println("h = " + h);
}
--案例2
public class Animal { // 父类
}
public class Person extends Animal { // 子类
}
public static void main(String[] args) {
// [4] 子类类型自动转化为父类类型
Animal animal = new Person();
}
--案例3
public static void main(String[] args) {
// [5] boolean类型不能和基本数据类型发生类型转化
boolean i = false;
int j = i; // 不能通过编译
}
2.1.2. JVM优化
可以将整型常量(int类型)直接赋值给byte、short、char类型变量,而不需要进行强制类型转换,只要不超出其表数范围。
--案例
public static void main(String[] args) {
byte g = 127; // [-128, 127]
short s = 32767; // [-32768, 32767]
char c = 65535; // [0, 65535]
}
2.2. 表达式的自动类型转换
当多个数据类型进行运算时,也会发生自动类型转换。
如果是整型和浮点型之间的准换,那么是比较谁的精确程度更高。转换图:
2.3. 强制类型转换
强转转换需要程序员人为的干预。
2.2.1. 触发情况
i. 容量大的数据类型需要强制转化成容量小的数据类型。
ii. 精度高的数据类型需要强制转化为精度低的数据类型。
iii. 父类类型需要需要强制转化为子类类型(向下造型)。
注意事项:
[1] 数据类型包括包装类型。
[2] boolean类型不能和基本数据类型发生类型转化。
2.2.2. 转化语法
目标类型 var2 = (目标类型) var1;
2.2.3. 两类丢失强制转换
2.2.3.1. 精度丢失
将浮点数装换为整数,浮点数的精度会丢失。
public static void main(String[] args) {
float f = 10.0f;
int i = (int) f;
System.out.println("i = " + i);
}
2.2.3.2. 信息丢失
一个数据类型接收了一个超过其表数范围的数值时,会发生信息丢失。
public static void main(String[] args) {
int i = 300;
byte b = (byte) i;
System.out.println("b = " + b);
}
注意:当将一种类型强制转换成另一种类型,而又超出了目标类型的表示范围,就会被截断成为一个完全不同的值。
3. 常见问题
--问题1:float e = 3.4;会报从double转化到float会有损失的错误。
计算机中的数值都是以二进制形式存储,在java中如果常量是整型,那么会默认使用int类型(4字节)存储,如果是浮点型,那么会默认使用double类型(8字节)。
将一个8字节的数值放进一个只有4字节的空间内,违背了“容量小的数据类型可以自动转化成容量大的数据类型,相反不可”,因此报错,需要进行强制类型转换,即由double类型转换为float类型,通过在3.4后面加上f或者F,一般使用f。
--问题2:long l = 2147483648;会报错
常量值如果是整数,那么默认占用32bit位来存储这个常量值,即int类型,int表数范围为【-2147483648, 2147483647】,显然2147483648已经不是一个int类型了,所以计算机不认识这个数,此时需要在2147483648后面加一个l或L,以表示这是一个long类型的数值,建议使用L,因为l可能和数字1傻傻分不清。
4. 总结
1. 整型常量值是int类型,浮点型常量是double类型。
2. 整型常量值可以直接赋值给byte、short、int、char,前提是不超过其表数范围,如果是整型变量,那么需要强制类型转换。
3. float数据类型的变量空间需要赋值的时候,要带上修饰符f/F,即强制类型装换,long数据类型也类似,当需要存储在long数据类型变量空间中的值超过了int类型的取值范围的时候,需要带上修饰符l/L,以表明这是一个long类型数值。
4. 数据类型相同,即整型和整型、浮点型和浮点型,它们之间的转换规则是比较内存空间的大小,即数据类型空间大的可以直接存储数据类型空间小的值,即自动类型转换,数据类型空间小的不可以直接存储数据类型空间大的值,即需要强制类型转换。
5. 数据类型不同,即 整型和浮点型,因为整型和浮点型的底层存储机制是不一样的,因此在数据类型转换的时候,那么就不是比较彼此之间的空间所占bit的大小了,而是 比较精确程度,并且浮点型的精确程度更高,整数的精确程度稍低,因此可以认为一个整型空间都可以直接存储一个浮点型的值,即自动类型转换,反之需要进行强制类型转换。
6. 虽然强制类型转换法好用,即能通过编译和执行,但会有可能会出现精度丢失和信息丢失。
7. 整型和字符型之间的对应(映射)关系是通过unicode编码来建立对应关系的。
8. 布尔数据类型是很特殊的基本数据类型,不能与其他的基本数据类型进行转换。
9. 当不发生数据丢失的前提下,基本数据类型转换仅仅只是值的存储空间大小发生了变换,而值还是那个值。