【Java】类型转换(自动、强制)--语言根基(一)
·
【Java】类型转换(自动、强制)--语言根基(一)
类型转换(自动、强制)——基础语法
简单说,类型转换就是把一种数据类型的值,变成另一种数据类型。比如把整数 100 变成浮点数 100.0,或者把字符串 “123” 变成数字 123。
一、基本类型转换
基本类型就是 Java 内置的那些简单类型:byte、short、int、long、float、double、char、boolean。
1. 自动类型转换(隐式/ widening)
当小范围类型赋值给大范围类型时,自动发生,无需显式声明。
- 类型兼容性等级(从小到大)
byte (1字节) → short (2字节) → int (4字节) → long (8字节) → float (4字节) → double (8字节)
↘
char (2字节) → int → long → float → double
提示:
float 虽然只有 4 字节,但因为它能表示小数的特殊存储方式,它可以装下 8 字节的 long 的所有整数(只是可能丢失精度)。
- 转换条件:
- 两种类型兼容(数值类型之间)
- 目标类型范围 ≥ 源类型范围
- 示例:
// 自动转换
byte b = 10;
short s = b; // byte → short
int i = s; // short → int
long l = i; // int → long
float f = l; // long → float(可能丢失精度)
double d = f; // float → double
// char → int(自动)
char c = 'A';
int code = c; // code = 65
// 字面量自动转换
int num = 100; // int 字面量
long big = 100L; // long 字面量
float pi = 3.14f; // float 字面量
double dbl = 3.14; // double 字面量
// 方法调用中的自动转换
void printDouble(double d) { }
printDouble(100); // int 自动转 double
2. 强制类型转换(显式/ narrowing)
将大范围类型赋值给小范围类型,或需要特定类型时。
-
语法:
目标类型 变量名 = (目标类型) 源值; -
示例:
// 基本强制转换
double d = 123.456;
int i = (int) d; // i = 123(截断小数)
long l = 100L;
byte b = (byte) l; // 可能溢出
// char 与 int 互转
int code = 65;
char c = (char) code; // c = 'A'
// 表达式强制转换
int a = 10, b = 3;
double result = (double) a / b; // 3.333... 而非 3
- 精度丢失与溢出
// 精度丢失
float f = 123.456f;
int i = (int) f; // 123(小数部分丢失)
// 溢出(模运算)
int large = 300;
byte b = (byte) large; // 二进制高位直接截断,不是取模运算
// 浮点转整数截断
double d = 9.99;
int floor = (int) d; // 9((int) 浮点值 = 向零取整,不是向下取整。)
int round = (int) Math.round(d); // 10(正确四舍五入)
3. 表达式类型提升
当你用运算符(如 +、-、*、/)计算时,Java 会悄悄把一些小类型"升级"成大类型,再计算。
- 提升规则:
byte/short/char参与二元算术运算时,操作数的值自动提升为int,变量本身类型不改变。- 若任一操作数为
long,则结果为long。 - 若任一操作数为
float,则结果为float。 - 若任一操作数为
double,则结果为double。
- 示例:
// byte/short/char 提升为 int
byte b1 = 10, b2 = 20;
// byte b3 = b1 + b2; // 编译错误:结果是 int
int sum = b1 + b2; // 正确
// 混合类型提升
byte b = 10;
short s = 20;
int i = 30;
long l = 40L;
float f = 50f;
double d = 60.0;
// 结果类型:double(最高优先级)
double result = b + s + i + l + f + d;
// 常见陷阱
int a = 5, b = 2;
double div = a / b; // div = 2.0(整数除法,结果先为 int)
double correct = a / (double) b; // 2.5
4. 基本类型转换速查表
| 源类型 | 目标类型 | 转换 | 风险 |
|---|---|---|---|
| byte | short/int/long/float/double | 自动 | 无 |
| short | int/long/float/double | 自动 | 无 |
| char | int/long/float/double | 自动 | 无 |
| int | long/float/double | 自动 | float可能丢精度 |
| long | float/double | 自动 | 可能丢精度 |
| float | double | 自动 | 无 |
| double | float | 强制 | 精度丢失 |
| double | int | 强制 | 小数截断+溢出 |
| long | int | 强制 | 溢出 |
| int | short/byte/char | 强制 | 溢出 |
二、引用类型转换
引用类型就是类、接口、数组这些"复杂类型"。
-
核心:
父类 = 更通用的类型(比如"动物")
子类 = 更具体的类型(比如"狗")
1. 向上转型(upcasting)- 自动
子类实例赋值给父类类型引用变量,自动发生,安全可靠。(这是把子类对象当作父类类型来用。)
注意:
转型后,只能访问调用父类中定义的方法,不能访问子类特有成员。但重写的方法仍然是子类的实现(多态的魅力)。
- 示例:
class Animal {
public void sound() { System.out.println("动物叫"); }
}
class Dog extends Animal {
@Override
public void sound() { System.out.println("汪汪"); }
public void wagTail() { System.out.println("摇尾巴"); }
}
// 向上转型(自动)
Animal animal = new Dog(); // 自动转换
animal.sound(); // 输出:汪汪(多态)
// animal.wagTail(); // 编译错误:父类无此方法
2. 向下转型(downcasting)- 强制
父类引用强制转换为子类类型,必须显式转换,可能抛出 ClassCastException。(这是把父类引用转回子类类型。强制、有风险。)
-
语法:
子类类型 变量 = (子类类型) 父类引用; -
示例:
Animal animal = new Dog(); // 向上转型
// 向下转型(需要强制)
Dog dog = (Dog) animal; // 正确,实际类型是 Dog
dog.wagTail(); // 可以调用子类方法
// 危险转型
Animal animal2 = new Animal();
Dog dog2 = (Dog) animal2; // 编译通过,但运行时抛出 ClassCastException
3. instanceof 安全转换
-
使用:
在向下转型之前,先用 instanceof 检查一下,确认类型正确再转。
public void handleAnimal(Animal animal) {
if (animal instanceof Dog) {
Dog dog = (Dog) animal; // 安全转换
dog.wagTail();
} else if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.meow();
}
}
// Java 16+ 模式匹配(增强)
if (animal instanceof Dog dog) {
dog.wagTail(); // 直接使用 dog 变量
}
4. 引用类型转换规则
| 转换 | 允许 | 方式 | 安全性 |
|---|---|---|---|
| 子类 → 父类 | 总是允许 | 自动(向上转型) | 安全 |
| 父类 → 子类 | 看实际情况 | 强制(向下转型) | 可能抛异常 |
| 同类型 | 允许 | 自动/强制 | 安全 |
| 不相关类型 | 不允许 | 编译错误 | - |
| 接口实现类 → 接口 | 总是允许 | 自动 | 安全 |
| 接口 → 实现类 | 看实际情况 | 强制 | 可能抛异常 |
三、特殊类型转换
1. 字符串与基本类型互转
- 基本类型 → 字符串
// 方法1:String.valueOf()
String s1 = String.valueOf(123);
String s2 = String.valueOf(45.67);
String s3 = String.valueOf(true);
// 方法2:拼接空字符串
String s4 = 123 + "";
// 方法3:包装类的 toString()
String s5 = Integer.toString(456);
String s6 = Double.toString(78.9);
- 字符串 → 基本类型
// 使用包装类的 parseXxx()
int i = Integer.parseInt("123");
double d = Double.parseDouble("45.67");
boolean b = Boolean.parseBoolean("true");
long l = Long.parseLong("9999999999");
// 可能抛出 NumberFormatException
int error = Integer.parseInt("abc"); // ❌ 异常
// 安全转换方法
public int safeParseInt(String str) {
try {
return Integer.parseInt(str);
} catch (NumberFormatException e) {
return 0; // 或抛出业务异常
}
}
2. 包装类与基本类型转换(自动装箱/拆箱)
// 自动装箱(Java 5+)
Integer obj = 100; // int → Integer
Double dObj = 3.14; // double → Double
// 自动拆箱
int primitive = obj; // Integer → int
// 注意事项
Integer a = null;
int b = a; // NullPointerException(拆箱时)
// 缓存池陷阱
Integer i1 = 100;
Integer i2 = 100;
System.out.println(i1 == i2); // true(-128~127 缓存)
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i3 == i4); // false(超出缓存范围)
// 应使用 equals()
System.out.println(i3.equals(i4)); // true
3. 数值类型与 char 转换
// int → char(Unicode)
char c = 65; // 'A'
// 正确的表情符号处理
int emojiCode = 0x1F600;
String emoji = new String(Character.toChars(emojiCode)); // 😀
// 或使用char数组
char[] emojiChars = Character.toChars(0x1F600);
// char → int
int code = 'A'; // 65
// 数字字符 → 数值
char digitChar = '5';
int digitValue = digitChar - '0'; // 5
// 数值 → 数字字符
int num = 7;
char digit = (char) (num + '0'); // '7'
4. 数组类型转换
// 数组向上转型(协变)
String[] strings = new String[10];
Object[] objects = strings; // 自动转换
// 数组向下转型(危险)
Object[] objs = new String[10];
String[] strs = (String[]) objs; // 正确
Object[] objs2 = new Object[10];
String[] strs2 = (String[]) objs2; // ClassCastException
// 基本类型数组不能互转
int[] ints = new int[10];
// Object[] objs = ints; // 编译错误(int[]是 Object 子类,但不是 Object[] 子类,不能赋值)
速查
| 转换 | 示例 |
|---|---|
| int → double | double d = i;(自动) |
| double → int | int i = (int) d;(截断) |
| double → int(四舍五入) | int i = (int) Math.round(d); |
| String → int | int i = Integer.parseInt(str); |
| int → String | String s = Integer.toString(i); |
| Integer → int | int i = integerObj;(自动拆箱) |
| 父类 → 子类(安全) | if (obj instanceof Dog d) { d.bark(); } |
| 数值 → 数字字符 | char c = (char) (num + '0'); |
| 数字字符 → 数值 | int num = c - '0'; |
总结
小转大自动做,大转小要强制;向下转型先检查,字符串转换防异常。
更多推荐




所有评论(0)