Java 零基础教程

Java 类型转换与强转

类型转换(Type conversion)和强制类型转换(Casting)是 Java 中极为基础但也容易踩坑的概念,它们赋予了你高效操作不同类型数据的能力。

由于 Java 是一门强类型语言(Strongly-typed language),这意味着每个变量都必须有严格的数据类型。理解如何在不同类型之间进行转换,对于执行数学计算、处理用户输入以及避免各种令人头疼的编译/运行时错误至关重要。

本章将全面覆盖不同种类的类型转换、何时需要它们,以及如何安全地执行这些操作。

1. 隐式类型转换 (自动扩大转换 / Widening)

隐式类型转换,也被称为“自动向上转型”或“扩大转换”,当你把一个较小数据类型的值赋值给一个较大数据类型的变量时,这种转换会自动发生。因为目标容器比源数据大,所以这种转换是绝对安全的,没有任何丢失信息的风险。

1.1 自动转换是如何工作的?

Java 编译器会在后台默默地将较小的类型转换为较大的类型,不需要程序员写任何额外的代码指令。以下转换路径是被允许自动发生的:

  • byte -> short, int, long, float, 或 double
  • short -> int, long, float, 或 double
  • char -> int, long, float, 或 double
  • int -> long, float, 或 double
  • long -> floatdouble
  • float -> double

1.2 隐式转换代码示例

public class ImplicitConversion {
    public static void main(String[] args) {
        int intValue = 100;
        
        // 隐式转换:从小杯子 (int) 倒进大杯子 (long),自动完成
        long longValue = intValue; 
        System.out.println("Long 值: " + longValue); // 输出: Long 值: 100
        
        // 隐式转换:long 转换为 float
        float floatValue = longValue; 
        System.out.println("Float 值: " + floatValue); // 输出: Float 值: 100.0
        
        // 隐式转换:float 转换为 double
        double doubleValue = floatValue; 
        System.out.println("Double 值: " + doubleValue); // 输出: Double 值: 100.0
        
        // 特殊情况:char 到 int 的自动转换 (转换为字符对应的 ASCII/Unicode 码)
        char charValue = 'A';
        int intFromChar = charValue; 
        System.out.println("字符转 Int: " + intFromChar); // 输出: 字符转 Int: 65
    }
}

2. 显式类型转换 (强制类型转换 / Casting)

显式类型转换,也被称为“向下转型”或“强制转换”,当你试图将一个较大数据类型的值塞进一个较小数据类型的变量时,必须使用这种方式。

把大杯子的水倒进小杯子可能会溢出,这就意味着潜在的数据丢失风险。因此,Java 编译器不允许这种操作自动发生,它要求你必须明确写下“强制转换”的代码,以此证明你清楚自己在做什么,并愿意承担数据丢失的后果。

2.1 强制转换的语法结构

强制转换的语法是:在需要转换的值之前,用小括号 () 括上目标数据类型。即 (目标类型) 值

以下这些“逆向”操作都需要强制转换:

  • short -> bytechar
  • char -> byteshort
  • int -> byte, short, 或 char
  • long -> byte, short, char, 或 int
  • float -> byte, short, char, int, 或 long
  • double -> byte, short, char, int, long, 或 float

2.2 强制转换代码示例与风险演示

public class ExplicitConversion {
    public static void main(String[] args) {
        // 1. 精度截断 (Truncation)
        double doubleValue = 19.99;
        int intValue = (int) doubleValue; // 强制将 double 转为 int
        System.out.println("Double 转 Int: " + intValue); // 输出: 19 (小数部分被直接一刀切,不会四舍五入!)

        // 2. 正常强转 (数值在安全范围内)
        long longValue = 200L;
        int intValueFromLong = (int) longValue; 
        System.out.println("Long 转 Int: " + intValueFromLong); // 输出: 200

        // 3. 数据溢出 (Overflow) - 极其危险!
        int largeIntValue = 130;
        // byte 的最大容量只有 127。把 130 强行塞进去会发生什么?
        byte byteValueFromInt = (byte) largeIntValue; 
        System.out.println("大 Int 强转 Byte: " + byteValueFromInt); // 输出: -126 (发生了底层的环绕溢出)
    }
}

深入理解数据溢出 (Overflow):
在上面的代码中,byte 的取值范围是 -128 到 127。当你试图把 130 强转为 byte 时,它装不下。这就好比汽车里程表爆表后会从 0 重新开始一样。130 比最大值 127 多出了 3 个单位,所以它会“绕回”到最小值,变成 -128 + (3 - 1) = -126。这在实际业务逻辑中通常是灾难性的 bug。

3. 字符串与基本类型的互转 (String Conversions)

在 Java 中,经常需要把用户输入的文本(字符串)转换成数字进行计算,或者把计算得出的数字转换成文本展示在屏幕上。请注意:你不能用上面讲的括号 (int) 语法来强转字符串! 字符串转换需要调用特定类提供的方法。

3.1 字符串转基本类型 (Parsing)

要将表示数字的字符串转换为基本数据类型,我们使用对应“包装类 (Wrapper Class)”的 parseXxx() 方法。

public class StringToPrimitive {
    public static void main(String[] args) {
        // 字符串转 int
        String intString = "123";
        int intValue = Integer.parseInt(intString);
        System.out.println("解析出的 Int: " + intValue); // 输出: 123
        
        // 字符串转 double
        String doubleString = "45.67";
        double doubleValue = Double.parseDouble(doubleString);
        System.out.println("解析出的 Double: " + doubleValue); // 输出: 45.67
        
        // 字符串转 boolean (只有字符串是 "true" 时才为真,忽略大小写)
        String booleanString = "TrUe";
        boolean booleanValue = Boolean.parseBoolean(booleanString);
        System.out.println("解析出的 Boolean: " + booleanValue); // 输出: true
    }
}

致命警告:
如果字符串里包含的不是合法的数字(比如 "123a""hello"),当你调用 Integer.parseInt() 时,程序会当场崩溃,并抛出一个 NumberFormatException 异常。在真实开发中,我们必须处理这种异常(我们将在后续的异常处理模块详细学习)。

3.2 基本类型转字符串

将数字或布尔值转换成字符串就简单得多了,最标准、最推荐的方法是使用 String.valueOf()

public class PrimitiveToString {
    public static void main(String[] args) {
        int intValue = 123;
        // 标准做法:使用 String.valueOf()
        String intString = String.valueOf(intValue); 
        System.out.println("转为字符串: " + intString);
        
        double doubleValue = 45.67;
        String doubleString = String.valueOf(doubleValue);
        
        boolean booleanValue = true;
        String booleanString = String.valueOf(booleanValue);

        // 另一种常见做法:直接与空字符串拼接 (利用了底层的自动转换特性)
        int anotherInt = 999;
        String easyString = anotherInt + ""; 
        System.out.println("拼接法转字符串: " + easyString);
    }
}