类型转换和强制类型转换、表达式中的自动类型提升

本文针对Java中的类型转换这一知识点展开叙述,用于对自己学习中的总结。

类型转换和强制类型转换
1、Java的自动类型转换

   当将某种类型的数据赋值给另外一种类型的变量时,满足如下两个条件,就会发生自动类型转换:
(1) 两种类型是兼容的
(2) 目标类型大于源类型
   当满足这两个条件时,会发生扩宽转换(widening conversion)。例如,要保存所有有效的byte值,int类型总是足够的,所以不需要显式的强制转换语句。
   对于扩宽转换,数值类型是相互兼容的。然而,不存在从数值类型到char或boolean类型的自动转换。此外char和boolean相互之间也不是兼容的。
   当将字面整数常量保存到byte、short、long或char类型的变量中时,Java也会执行自动类型转换。例子如下:

//代码1
char b='a'+1;//自动类型转换
//代码2
char a='a';
/*
声明变量a,使用变量进行运算idea报错Required:char,Found:int
正确写法:char b= (char) (a+1);
*/
char b=a+1;
/*
原理剖析:
'a',是一个常量值(这里写'a'和97是一样的,默认都是int类型的常量,加上单引号是为  	
了告诉我们这里只能放char规定范围内的数值),故char = 'a' + 18就是两个int类型的  	
常量进行运算,然后生成一个新的int类型的常量,然后把这个新的int类型的常量赋值给	
char类型的变量b,进行了自动类型转换(常量的值赋值给变量不存在强制类型转换,只要	
这个变量的类型取值范围能够容纳新的常量即可)。
char a='a',这个a是变量,仅仅是把常量的值赋值给变量,这个数'a'这个int值传递给了	
char,这时候a就是char类型了(将字面整数常量保存到char类型的变量中,Java执行自动类型转换)。
char b = a + 1,报错是因为a已经分配了一个内存空间用于存放char类型变量a,然后把a	
赋值一份到内存,用赋值的值与int类型的常量1进行运算,生成一个变量值,然后把这个	
变量赋值给变量b,因为是变量存在着类型转换的问题,原理是1和a分别处于不同的内存块	
当中,这时候传递给b的是两个内存空间的值,这时候就存在转换问题了。
*/
2、强制转换不兼容的类型

   如果希望将int类型的值赋给byte变量,不会自动执行转换,因为byte比int更小。这种转换有时候被称为缩小转换(narrowing conversion),因为是显式地使数值变得更小以适应目标类型。
   为了实现两种不兼容类型之间的转换,必须使用强制类型转换。下面的demo演示了一些需要进行强制类型转换的转换:

public class Conversion {
    public static void main(String[] args) {
        byte b;
        int i = 257;
        double d = 314.159;
        /*
        将int类型的值强制转换为byte类型。如果整数的值超出了byte类型的范围,
        结果将以byte类型的范围为模(用整数除以byte范围后的位数)减少。
        这里byte的取值范围为-128-127,i的值为257,超出了byte类型的范围
        b=(byte)i,进行的运算是b=257%257,即b=1。
         */
        b= (byte) i;
        System.out.println("i and b "+i+" "+b);//输出结果 i and b 257 1
        /*
        当将浮点值赋给整数类型时会发生另外一种不同类型的转换:截尾(truncation)。
        由于整数没有小数部分,因此,当将浮点值赋给整数类型时,小数部分会丢失。
        如果整数部分的数值太大,以至于无法保存到目标整数类型中,那么数值将以
        目标类型的范围为模减少。
         */
        /*
        i=(int)d,由double类型转换成int类型,需要截尾得到整数314,由于314在
        int类型的取值范围-2^31-2^31-1之间,故不需要再做其它操作,即i=314
         */
        i= (int) d;
        System.out.println("d and i "+d+" "+i);//输出结果 d and i 314.159 314
        /*
        b=(byte)d,由double类型转换成byte类型(由浮点型转换为整型),需要进行
        截尾操作,截尾操作后得到整型数314,由于314超出了byte类型的取值范围
        -128-127,故需要进行取模操作b=314%256,即b=58
         */
        b= (byte) d;
        System.out.println("d and b "+d+" "+b);//输出结果 d and b 314.159 58
    }
}
表达式中的自动类型提升

   除了赋值外,在表达式中也可能会发生某些类型转换。在表达式中中间值要求的精度有时会超出操作数的范围。例如:

byte a = 40;
byte b = 50;
byte c = 100;
int d = a * b / c;

   中间部分ab的结果很容易超出byte操作数的范围。为了解决这类问题,当对表达式求值时,Java自动将每个byte、short或char操作数提升为int类型。即使用int类型而不是byte类型执行子表达式ab。因此,尽管a和b都被指定为byte类型,中间表达式(40*50)的结果2000也是合法的。尽管自动类型提升很有用,但是它们会导致编译时错误,例如:

byte b = 50;
b = b * 2;//Error! Cannot assign an int to a byte!

   上面的demo试图将50*2这个完全有效的byte值,保存在一个byte变量中。但是,当计算表达式的值时,操作数被自动提升为int类型,所以结果也被提升为int类型。因此,如果不使用强制类型转换,就不能讲结果赋给那个byte变量。尽管对于这个特定情况来说,所赋予的值仍然满足目标类型,但是仍然需要进行强制类型转换。正确操作:

byte b = 50;
b = (byte)b * 2;//得到正确的值100
类型提升规则

1、所有byte、short和char类型的值都被提升为int类型。
2、如果有一个操作数是long类型,就将整个表达式提升为long类型。
3、如果有一个操作数是float类型,就将整个表达式提升为float类型。
4、如果任何一个操作数是double类型,结果将为double类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值