首页 > 编程笔记 > Java笔记 阅读:18

Java类型转换详解(隐式类型转换+强制类型转换)

我们编写 Java 代码时有时会将某种类型的数值赋值给另一种类型的变量,比如存在一个 int 类型的变量 a,现在要将一个 double 类型的数值 4.0 赋值给变量 a,此时就涉及类型转换问题,如下图所示。


图 1 类型转换

只有将一个数值转换成变量的类型才能将其赋值给该变量,否则将会导致赋值操作产生错误。

对于互相兼容的两种类型,Java 编译器会在编译时根据类型自动转换,而对于互不兼容的两种类型则需要我们在代码中添加转换逻辑。

根据这两种情况可以将类型转换分为两种方式:隐式类型转换(自动类型转换)和显式类型转换(强制类型转换)。

Java隐式类型转换

隐式类型转换由编译器负责转换工作,不在 Java 代码层面显式指定转换。这种转换方式一般用于由较少位的类型向较多位的类型转换,这样才能避免信息丢失。


图 2 隐式类型转换

如图 2 所示,8 位空间的类型可以转换成 16 位、32 位或 64 位的类型,其他转换也类似,都是由较少位到较多位的类型转换。由于更多位的空间能保存的信息更多,因此这种转换能做到不丢失信息。

下面来看看 Java 的 8 种基本数据类型之间是如何进行隐式转换的,下图能让大家清晰看到它们之间的转换关系。


图 3 隐式转换关系

上图中的箭头表示某种类型可以转换成所指向的类型。

需要注意的是,如果某种类型能通过箭头间接流转到另一种类型,则说明这个转换也是可行的,比如 byte 类型到 float 类型,由于 byte 可以先转换到 short,再转换到 int,最后转换到 float,因此 byte 类型可以隐式转换成 float 类型。跟着图 3 可以依次列出每种数据类型的隐式转换的情况。

结合上述介绍的转换情况我们看一个实例,其中符合隐式转换的都可以直接进行赋值,编译器编译时便会自动完成转换工作。
public class TypeCastingAutoTest {
    public static void main(String[] args) {
        byte b = (byte) 22;
        short s = (short) 33;
        char c = 'a';
        int i = 55;
        long l = 66L;
        float f = 77.0f;
        int byte2int = b;
        long short2long = s;
        long int2long = i;
        float long2float = l;
        int char2int = c;
        double float2double = f;
        System.out.println("byte类型隐式转为int类型:" + byte2int);
        System.out.println("short类型隐式转为long类型:" + short2long);
        System.out.println("int类型隐式转为long类型:" + int2long);
        System.out.println("long类型隐式转为float类型:" + long2float);
        System.out.println("char类型隐式转为int类型:" + char2int);
        System.out.println("float类型隐式转为double类型:" + float2double);
    }
}
输出结果为:

byte类型隐式转为int类型:22
short类型隐式转为long类型:33
int类型隐式转为long类型:55
long类型隐式转为float类型:66.0
char类型隐式转为int类型:97
float类型隐式转为double类型:77.0


再看看下面不兼容类型转换的例子:
public class TypeCastingAutoErrorTest {
    public static void main(String[] args) {
        float f = 77.0f;
        int float2int = (int) f; // 显式强制类型转换
    }
}
运行失败,报错信息是:

TypeCastingAutoErrorTest.java:5: 错误: 不兼容的类型: 从float转换到int可能会有损失
                int float2int = f;
                                ^
1 个错误

程序中本来的意图是将 float 类型隐式转换为 int 类型,但当我们执行javac TypeCastingAutoErrorTest.java命令进行编译时却发现报了不兼容的错误。因为浮点类型数值转为整型数值可能会导致精确度降低,比如 10.1 转成整数后变为 10,所以不能直接进行隐式转换。

Java显式类型转换

前面提到对于两种互相兼容的类型,可以由编译器自动完成隐式转换,而对于不兼容的类型则需要我们自行进行显式类型转换,接下来就介绍显式类型转换。

显式类型转换也被称为强制类型转换,需要在代码中显式地指定转换工作。这种转换方式一般由较多位的类型向较少位的类型转换,因此很可能会造成信息丢失的情况。

如下图所示,64 位的类型可以强制向 32 位、16 位和 8 位的类型进行转换,其他类似。


图 4 显式类型转换

Java 的 8 种基本数据类型之间的显式转换可以通过下图来了解。


图 5 显式转换关系

很明显,图 5 与图 3 的主要不同之处就是箭头的方向相反。总体而言,箭头由较多位类型指向较少位类型,比如 double 指向 int。图 5 列出了每种数据类型可进行显式转换的情况。

注意,没必要死记硬背这些转换关系,使用时查阅即可,或者用程序测试一下看看有没有报错就知道了。

显式转换的语法相当简单,只需在变量前面用括号指定类型,就能将该变量转换成指定类型。例如将 double 类型变量 d 转换为 int 类型,只需在变量 d 前面加上“(int)”。

下面给出显式转换的例子:
public class TypeCastingExplicitTest {
    public static void main(String[] args) {
        char c = 'a';
        int i = 55;
        long l = 66L;
        float f = 77.0f;
        double d = 65.0;
        byte long2byte = (byte) l;
        char double2char = (char) d;
        short char2short = (short) c;
        int float2int = (int) f;
        char int2char = (char) i;
        System.out.println("long类型显式转为byte类型:" + long2byte);
        System.out.println("double类型显式转为char类型:" + double2char);
        System.out.println("char类型显式转为short类型:" + char2short);
        System.out.println("float类型显式转为int类型:" + float2int);
        System.out.println("int类型显式转为char类型:" + int2char);
    }
}
输出结果为:

long类型显式转为byte类型:66
double类型显式转为char类型:A
char类型显式转为short类型:97
float类型显式转为int类型:77
int类型显式转为char类型:7

可以看到显式转换必须在代码的前面用括号声明要强制转换的类型。

相关文章