一、类型转换概述
在 Java 中,当不同数据类型的变量或值进行运算、赋值时,需要进行类型转换。类型转换分为两种:自动类型转换(隐式转换)和强制类型转换(显式转换),其核心依据是数据类型的 “取值范围”(或 “容量”)。
二、自动类型转换(隐式转换)
1. 定义
当两种数据类型兼容,且目标类型的取值范围大于源类型时,Java 会自动将源类型转换为目标类型,无需手动干预,称为自动类型转换,具体转换规则如下图。
2. 核心规则
- “小转大” 安全:取值范围小的类型可以自动转换为取值范围大的类型(不会丢失数据)。
- 基本数据类型转换顺序(按取值范围从小到大):
byte → short → int → long → float → double
(注:char
类型比较特殊,会先转换为int
再参与其他转换,即char → int → long → ...
)
3. 常见场景及示例
(1)赋值时的自动转换
当将 “小范围类型的值” 赋值给 “大范围类型的变量” 时,自动转换:
byte b = 10;
short s = b; // byte → short(自动转换)
int i = s; // short → int(自动转换)
long l = i; // int → long(自动转换)
float f = l; // long → float(自动转换,float范围比long大)
double d = f; // float → double(自动转换)
(2)运算时的自动转换
不同类型的变量混合运算时,会先自动转换为 “范围最大的类型”,再运算:
int a = 10;
double b = 3.14;
double sum = a + b; // int自动转换为double,结果为double
(3)char 类型的特殊转换
char
类型本质是 Unicode 编码(无符号整数),会自动转换为int
及更大范围的类型:
char c = 'A'; // 'A'的Unicode编码是65
int num = c; // char → int(自动转换,num的值为65)
long l = c; // char → int → long(自动转换)
(4)常量的自动转换
当整数常量的值在目标类型范围内时,可直接赋值(即使类型不同):
byte b = 127; // 127是int常量,但在byte范围(-128~127)内,自动转换
short s = 32767; // 32767是int常量,在short范围(-32768~32767)内,自动转换
三、强制类型转换(显式转换)
1. 定义
当需要将取值范围大的类型转换为取值范围小的类型时,Java 不会自动转换,必须手动使用 “强制转换符”(目标类型)
,称为强制类型转换。
2. 语法格式
目标类型 变量名 = (目标类型) 源类型的值;
3. 常见场景及示例
(1)赋值时的强制转换
将 “大范围类型的值” 赋值给 “小范围类型的变量” 时,必须强制转换:
double d = 3.14;
int i = (int) d; // double → int(强制转换,i的值为3)
long l = 10000000000L;
int num = (int) l; // long → int(强制转换,结果可能溢出)
(2)运算后的强制转换
byte/short/char
类型的变量运算时,结果会自动提升为int
,若需赋值回原类型,必须强制转换:
byte b1 = 10;
byte b2 = 20;
// byte sum = b1 + b2; // 编译报错:b1+b2结果为int,不能直接赋值给byte
byte sum = (byte) (b1 + b2); // 强制转换为byte(sum的值为30)
4. 强制类型转换的风险
(1)精度损失(针对浮点型转整数型)
浮点型(float
/double
)转换为整数型(byte
/short
/int
/long
)时,会直接截断小数部分,丢失精度:
double d = 9.99;
int i = (int) d; // 结果为9(小数部分.99被截断,不是四舍五入)
float f = 3.14f;
long l = (long) f; // 结果为3(丢失小数部分)
(2)数据溢出(针对整数型之间的转换)
当源类型的值超过目标类型的取值范围时,转换结果会 “溢出”,得到错误的数值(底层二进制截断导致):
int i = 300;
byte b = (byte) i; // byte范围是-128~127,300超过范围,结果为44(溢出错误)
long l = 2147483648L; // int最大值是2147483647
int num = (int) l; // 结果为-2147483648(溢出错误)
(3)布尔类型不可转换
boolean
类型与任何其他类型(包括基本类型和引用类型)都不兼容,不能进行任何类型转换:
boolean flag = true;
// int i = (int) flag; // 编译报错:不兼容的类型
四、引用数据类型的转换(补充)
引用数据类型的转换仅适用于有继承 / 实现关系的类型(如子类与父类、实现类与接口),分为:
-
向上转型(自动转换):子类对象 → 父类 / 接口类型(安全,无需强制转换)
class Dog extends Animal {} Animal animal = new Dog(); // Dog(子类)→ Animal(父类),自动转换
-
向下转型(强制转换):父类 / 接口类型 → 子类类型(有风险,需先用
instanceof
判断)Animal animal = new Dog(); if (animal instanceof Dog) { // 先判断,避免类型转换异常 Dog dog = (Dog) animal; // 强制转换,安全 }
- 风险:若父类引用的对象不是目标子类类型,会抛出
ClassCastException
(类型转换异常)。
- 风险:若父类引用的对象不是目标子类类型,会抛出
本节关于类型转换还可以参考