类型转换(自动、强制)——基础语法

简单说,类型转换就是把一种数据类型的值,变成另一种数据类型。比如把整数 100 变成浮点数 100.0,或者把字符串 “123” 变成数字 123。

一、基本类型转换

基本类型就是 Java 内置的那些简单类型:byteshortintlongfloatdoublecharboolean

1. 自动类型转换(隐式/ widening)

当小范围类型赋值给大范围类型时,自动发生,无需显式声明。

  • 类型兼容性等级(从小到大)
byte (1字节) → short (2字节) → int (4字节) → long (8字节) → float (4字节) → double (8字节)
    ↘
   char (2字节) → int → long → float → double

提示:
float 虽然只有 4 字节,但因为它能表示小数的特殊存储方式,它可以装下 8 字节的 long 的所有整数(只是可能丢失精度)。

  • 转换条件:
  1. 两种类型兼容(数值类型之间)
  2. 目标类型范围 ≥ 源类型范围
  • 示例:
// 自动转换
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 会悄悄把一些小类型"升级"成大类型,再计算。

  • 提升规则:
  1. byte/short/char 参与二元算术运算时,操作数的值自动提升为 int,变量本身类型不改变。
  2. 若任一操作数为 long,则结果为 long
  3. 若任一操作数为 float,则结果为 float
  4. 若任一操作数为 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';

总结

小转大自动做,大转小要强制;向下转型先检查,字符串转换防异常。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐