欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

45.再说类型转换

程序员文章站 2022-04-29 12:34:41
...

在之前的内容中,我们已经知道了,数值简单数据类型数据之间是可以相互转换的。那么,在表达式中,它是如何转换的呢?比如,如果一个表达式中既有float类型的数据,又有double类型的数据,那么,得出来的结果到底是什么数据类型呢?


Java在编译期间就会进行扩展类型检查,并且在数据从一种类型转换到另一种类型时有严格的限制。


我们知道,在Java中,存在两种不同类型的类型转换:


隐式转换:在对包含非boolean简单数据类型(primitive type)的表达式求值的时候,Java会进行大量的隐式类型转换。

 

这些转换有很大的限制,但最基本的原则是这种转换必须是提升(widening,或称为扩大)而不是下降(narrowing,或称为缩小)转换。也就是说,隐式转换只能将一种简单数据类型转换到比它范围更大的类型。


强制类型转换:当隐式转换不能被我们所要求的表达式支持,或者是有特殊的需求,则需要进行强制的类型转换,这时候需要使用类型转换运算符进行强制转换。

 

对于单目(一元)运算符,例如++或--,隐式转换比较简单: byte、short、char类型的数被转换成int的,而其他类型的数据保持不变。


对于二元运算符,情况比较复杂,但是这种转换基本上遵循如下的基本方式:表达式中最长的类型为表达式的类型。下面是具体的运算规则:
1. 如果两个操作数中有一个是double类型的,则另一个也将会转换成double类型的,最后的运算结果也是double类型的,也就是说表达式的类型为double类型;否则
2. 如果两个操作数中有一个是float类型的,则另一个操作数也会转换成float类型的,此时表达式类型float类型;否则
3. 如果两个操作数中有一个是long类型的,另一个将会转换成long类型,此时,表达式的类型也为long类型,否则
4. 两个操作数都会转换成int类型。

 

对于byte/char/short类型的数据,在进行计算时都会转换成int类型来计算,得出的结果也是int类型。这点需要加以注意。

 

下面来看一个例子。

 

public class Implicit {
 public static void main(String[] agrs) {
  short s = 10;
  long l = 100;
  System.out.println(l * s);// 将会得到一个long类型的数值
  int a = 1;
  byte b = 2, e = 3;
  char c = 'a';
  int d = b + c;
  // byte f = b+e; //将会报错,因为计算得出的结果应该是int类型
  int i = 1234567809;
  float j = i;// 将会损失精度,得到的结果是1.23456781E9
  System.out.println(j);
  System.out.println(d);
 }
}


在这个例子中,如果将两个byte类型的数据相加,将结果赋给一个byte类型的变量,编译的时候将会出错,这是因为两个byte类型的值相加返回的是int类型的值。而如果将一个整型的值赋给一个float类型的变量,则会保留正确的数值级数,

 

但是,从例子中的结果可以看出,转换后已经损失了一些精度。


虽然不能将一个会产生int类型结果的表达式的值赋给byte类型变量,但是实际上,可以将整型值直接赋值给byte/short/char等“更窄”类型的变量,而不需要进行强制类型转换,只要不超出其表数范围即可。
例如:
byte b1 = 33;   //合法
byte b2 = 131   //非法,超出byte型数据表数范围
short s = 456;   //合法
char ch = 345;    //合法


隐式转换不但发生在表达式中,还发生在方法调用的时候。比如,当调用方法时的参数不是方法定义中所规定的参数类型的时候。


在上面已经讲过,Java可以自动“提升”数据类型,但是,经常的,我们需要将数据从较长的类型转换到较短的类型,如将double类型的数据转换成int 类型的数据,这个时候,Java 不会自动完成这个动作(默认情况下只会将int类型的数据转换成double类型的),所以,需要我们在程序中对其进行强制转换。当然,这种操作可能会引起信息的丢失。


在Java中,是通过运算符“()”来进行强制类型转换的。运算符“()”中应该有一个将要转换成的目标数据类型。


来看下面这个例子:
public class Explicit {
 public static void main(String[] args) {
  double x = 9.987;
  int i = (int) x;
  System.out.println(i);
 }
}


运行这个程序,将在控制台上打印初一个数字9。可以看出,在进行强制转换的时候只是简单的将小数截去了,而只保留了整数部分。


由于在将数值进行“缩小”强制类型转换时会导致数据的信息丢失,所以应该尽量小心使用。


除了简单数据类型外,类型转换还可以引用于引用类型的数据。任何对象都可以被转换成它的基类或任何它所实现的接口。一个接口也可以被转换成它所扩展的任何其他接口。关于这部分的内容,请看后续的章节。