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

图 1 类型转换
只有将一个数值转换成变量的类型才能将其赋值给该变量,否则将会导致赋值操作产生错误。
对于互相兼容的两种类型,Java 编译器会在编译时根据类型自动转换,而对于互不兼容的两种类型则需要我们在代码中添加转换逻辑。
根据这两种情况可以将类型转换分为两种方式:隐式类型转换(自动类型转换)和显式类型转换(强制类型转换)。

图 2 隐式类型转换
如图 2 所示,8 位空间的类型可以转换成 16 位、32 位或 64 位的类型,其他转换也类似,都是由较少位到较多位的类型转换。由于更多位的空间能保存的信息更多,因此这种转换能做到不丢失信息。
下面来看看 Java 的 8 种基本数据类型之间是如何进行隐式转换的,下图能让大家清晰看到它们之间的转换关系。

图 3 隐式转换关系
上图中的箭头表示某种类型可以转换成所指向的类型。
需要注意的是,如果某种类型能通过箭头间接流转到另一种类型,则说明这个转换也是可行的,比如 byte 类型到 float 类型,由于 byte 可以先转换到 short,再转换到 int,最后转换到 float,因此 byte 类型可以隐式转换成 float 类型。跟着图 3 可以依次列出每种数据类型的隐式转换的情况。
结合上述介绍的转换情况我们看一个实例,其中符合隐式转换的都可以直接进行赋值,编译器编译时便会自动完成转换工作。
再看看下面不兼容类型转换的例子:
显式类型转换也被称为强制类型转换,需要在代码中显式地指定转换工作。这种转换方式一般由较多位的类型向较少位的类型转换,因此很可能会造成信息丢失的情况。
如下图所示,64 位的类型可以强制向 32 位、16 位和 8 位的类型进行转换,其他类似。

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

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

图 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 个错误
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