00:00
那讲完宽化类型转换之后啊,咱们下边来看一下叫窄化类型转换。这个咱们平时在Java语言中讲解的话呢,我有时候习惯上把它称为呢,叫强制类型转换,这个主要呢,是从我们在具体操作的这个语言代码,把这个形式上来看,我们想把这个这个容量大的这种类型往容量小的类型转的时候呢,需要使用个强转弧,所以称为呢叫做强制类型转换了,在这儿呢,我们叫窄化,实际上呢也比较好理解,相较于我们说宽化呢,大家可以这样去看,比如说你这块呢,是一条。这条的话呢,你现在不断的往前走,往前走着走的时候呢,到这个路口的时候,发现下边这个再走的话呢,这个变宽了,那这呢,我们就可以理解成了叫宽化类型转化也比较形象嘛,那这个宽度呢,咱们就可以来衡量你这个数据的一个容量,咱们拿这个宽度来衡量容量,那就相当于你把这个容量小的是不是就转化成这个容量大的这个类型了。
01:00
这呢就是咱叫宽化类型转化,那相应的话呢,如果你这是一条路。然后这条路的话,你再往前走的时候呢,发现在下个路口的时候,发现这个路呢,变得特别窄了。那这就有问题了,对吧,这个路特别窄了,然后我们现在这个容量大的,你就转化成是这个容量小的了,那就是称为呢,叫窄化类型转化,那很容易看出来的,就是我们这个容量大的把容量往容量小的这块去转的时候呢,是不是就很容易的出现这种精度损失问题啊。我们容量大嘛,你容量小的精度损失了对吧,那这个容量小的往容量大的一块转的时候呢,按说好像说不该出现精度损失,但是我们说也确实出现了。对吧,咱们刚才讲框话的时候,不也出现精度损失问题了嘛,对吧,那么这个出现的问题,咱们归结原因是什么呢?是我们这衡量的是容量大小,它背后呢还依靠了一个存储范围。不能叫存储范围了,应该叫这个使用的字节数,那这里边儿呢,典型的就是我们说这个long往你这个float去转,虽然float从这个容量上来讲更大,但是它的精度更差,这是相当于是另外一个纬度了,这个大家呢去体会一下啊。
02:12
那像这种宽化和窄化的话呢,其实也特别好去理解,你像大学刚毕业的时候,大学呃,读研究生吧,比如在北京这块是吧,这个当时呢,北航是在这个三环四环之间,海淀区这块,然后我们都住住宿舍嘛,对吧,都住宿舍,然后后来毕业之后呢,就出来住了,出来住的时候呢,一开始这个大家想住的舒服一点,那舒服的话呢,你显然不能在市区这里边去租房子了,对吧,然后这时候呢,就到这个当时是霍营这块来租房子,那十年前的话呢,这货营的这个房租还是比较便宜的,就是大家几个人就租了一套房子,那么把这个行李呢,都放进去之后呢,发现屋里边还挺空的,因为租了一个客厅也很大,相当于是一个大的两居室了,那把东西呢,整个宿舍东西几个人都放过去之后呢,发现屋里边还挺空的,因为这时候你东西少放到一个。
03:01
这个空间大的一个地方,类似于我们这里边宽化一样,就完全能放得下是没问题的,对吧,但是后来的话呢,有的人去这个这个阿里了。在高德呢,啊,有一个拿去的腾讯了,后来呢,他们有的就在这个望京啊,在朝阳啊,在哪儿呢?呃,就渐渐的后来大家就分开住了,然后再分开住的时候呢,因为又回到这个市区了,这个时候呢,就租了一间屋子,这一间屋子呢,比原来这个就小很多了,这个时候再回去,再把这个东西移过去的时候发现啊,怎么东西这么多是吧,都盛不下了,所以有些东西呢就扔了。那就有点像我们把这个容量大的往容量小的去转的时候呢,就很容易的出现这种精度损失的这个问题。OK,嗯,这个大家应该能理解对吧?行,那我们下边来具体看一下,这个窄画的时候呢,具体转换的一些指令有哪些,那这里边呢,就看到了,我们强调了像BAT short和char类型了,从in的类型转换成BAT short char的时候,有I To B to CS,很好理解对吧?这个对应关系没有完全对应关系啊,这个你要说这个第一个跟这个第一个这个第二个,这就这个这写S是吧。
04:04
那这个呢,改成C吧,这样更严谨一点。然后这个long类型的话呢,就是l to I,然后float呢,转换成in的float转换成long,那就是f to if to l,大部分呢,往这转就是d to ID to LD to f,这个很好理解,大家一看这个首字母应该知道什么意思,行,那这里边呢,大家有没有发现一个问题呢?还有什么问题呢?比如我要是把一个float类型的数据转化成一个bad类型,怎么没有这个f to这个B呢?或者说FTOC是吧,是不是都没有啊。那这里边呢,我们要强调就是如果把这些呢都加上我们这个指令呢,肯定又非常多了,那尽尽量呢,我们希望呢是简化一些指令,另外的话呢,虽然说简化吧,但是我们也不能影响现有的使用,那如果我们就是讲将一个float型转化成个bad型怎么办呢?来咱们看一下具体的代码测试,大家就能明白了。下边呢,就是关于这个窄化类型转化,我们说这个基本的使用。
05:04
行,那首先这块呢,我们把刚才提到这几组呢,这个进行一个测试,首先呢,我定一个at这个int类型的一个I转化成be short叉没问题,然后我这呢,就写了一个long类型的,然后往这个in转,往这个bit转,像这块呢,就已经能够发现咱们刚才说的这个问题了,因为咱们在这块的时候呢。在这块时候呢,我是不是没有说这个long类型转换成一个bit啊,但是我们现在有一个long转成bit这样的一个需求嘛,大家看一下这块如何处理的,对吧?行,那把它打开咱们看一下,当CA1。看一下这个cold。行,那咱们这呢,主要还是找这个核心的这个操作了,关于这个push啊,No,这个咱们就包括load咱就过滤掉了,我这定一个I是十,然后把这个I呢,附给一个BA类型,大家会看到这个指令To B对吧,然后少的类型,叉类型相应的都有I to sc,那对应的就是我们这里边的这三个核心的这个指令,呃,核心的代码操作,再接下来我们定一个long型的L是十。
06:06
对吧,我们使用这个l DC two-W,这个咱们昨天也都说过了,对吧,那这里边的话呢,我们是用的这个把long类型的转换成是一个in的类型,咱们用的是l to I。还有to I那这块呢,这不就转换成一个int类型了吗。然后接下来呢,注意核心的来了,我们把这个long类型转化成bad类型,大家会发现有两个指令去支持。首先呢,我们是把这个long类型转换成int类型,那到int类型之后呢,Int再去转换成一个BA类型,就是这样的一个支持。那刚才我们提的那个问题,我想从float转化成是一个BAT,这个大家是不是就也清楚了,先把这个float我们使用叫f to I转化成是一个int类型,然后int呢,再到BAT类型I To B,哎,这就搞定了。就是也得有两个指令的去支持,那其他的这种情况我们又举例子呢,应该大家也能类似的,是不是把这个情况给他列举出来对吧,那下边你看我们又写了个这样例子,大家再来看一看。
07:06
好。我这呢,我这呢定类是一个float的类型,你看我就往这个这个容量小的这个呢去转了,那我们由float转换成是一个long,是不是直接有支持float转换成是个int,也有直接的支持float转换成是一个bad类型,先把float转换成ii tobe。OK,能理解double类型转换成bad类型,Double呢,也是先到ii呢,再到B。这样的一个场景。I带到B,那有没有同学这样想呢?说呢,咱们这里边儿也有一个指令呢,是从double呢到float d to f对吧?说我们从这个double呢转换成BA,那你怎么不先调一个d to f,然后再调一个f to I,然后再调一个I To B呢?你这个说法其实说完之后呢,自己应该都都能理解了,你这个咔咔来三次,那我们这儿呢,是不是直接有一个地图,哎呀。
08:05
相当于把这两个就不用在中间绕一下了,我直接有个现成的,那干什么,我们不用这个直接图ii在To B呢,对吧,所以我们肯定是这样去转。行,就是我们这里边儿没有什么歧义,或者说存在说诶是不是可能这样转,也可能这样转,没有咱们就会有一个最短的一个路径去转换,一般呢,是超不过两个对吧,因为只要呢,你相应的,你看这些指令呢,咱们是不是都支持往这个I这块去转吧,只要到了I之后呢,你顶多再来一个I to什么,不就完事了吗。能行对吧,行,这是我们说的这个问题。好,那这是关于我们说的窄化类型的一个基本情况,然后下边呢,提到一个窄的一个经度损失问题,这个事儿呢,我觉得大家应该是很好理解的,就像刚才我给大家举的例子,你一个窄的路,然后呢,呃,这相对窄的一个路,然后去了另外一个更窄的路,你要开了一个车,本来这个车呢,这个还能走这条路,然后再往下走的话呢,这条路变窄了,那走不过去了,这就我们这呢叫经度损失,或者呢,你住了一个大房子,然后现在呢,把这个家呢,搬到一个小房子里边,东西呢,原来还挺多的,现在你搬到小家肯定是盛不下嘛,那这个盛不下呢,需要扔东西,这就是我们要损失精度的问题。
09:15
那转化类型转化呢,可能会导致这个转化的结果,具备不同的正负号,它竟然竟然连符号呢都可能会变化,这个要注意不同的这个数量级,因此呢,在转化过程当中可能会导致数据的精度损失。下边又说了,尽管呢可能会发生向上溢出啊,向下溢啊,进度损失啊等等,但是在Java中明确规定数值类型的窄化转换不会导致扎虚机抛一个运行时异常。因为对于这个我们计算机来讲的话呢,你这个比如容量比较大,占八个字节的,你想这块呢,砍一半把刀位呢,砍掉只留下低位的,这个计算机的话呢,或者程序的话呢,它不认为有什么问题,你不要砍嘛,那就砍呗,剩下是几是几就算几对吧,所以说你原来是个正数,最高位是个零,结果这个砍掉之后呢,保留的这个数据的最高位,结果发现这是一了,那就变成个负数了,那变就变呗。
10:08
那这时候呢,注意它没有出现任何异常。对吧,没有出现任何异常,这个大家要理解行,那关于这个嗯,精度损失的问题呢,下边咱也写了相应的这个代码。窄化类型转换的精度损失。这个情况行,那这里呢,你看我定义了一个啊,这还不是这个事儿,这个CTRLX这个我们说明这个问题是在这儿的啊,那你大家你看一下上面这个情况,上面情况呢,还是说的咱们基本使用我这呢,又举了一个特别的例子,我这整了一个short类型的是吧,有点意思啊,Short类型我要往bed类型去转。大家觉得会是什么样的呢?好像说诶,那有没有一个To B呢。I To B啊,没有啊,那这时候呢,你能想象出来是什么吧?
11:01
那我们就把这个呢,是不是就看成是一个int类型了,所以这个把S呢,转换成short类型,转换成败类型,那直接就是一个I To B啊哎,这就可以了啊行,然后下边呢,咱们看这个精度损失的情况。这个情况呢,大家应该在学习Java语言的时候呢,也见过或者写过类似的这个代码了,我这定一个I,这个in的类型是128,我就把128呢强转成是一个BAT类型,那很显然我们BAT的最大值是127,那这块一转的话呢,有同学想这是不是127呢?很遗憾不是对吧。这块咱们主要呢,还是跑一下这个程序这块指令的话呢,没什么可说的,就是咱们说的基本指令呗,对吧,关键的是我们发现这个数据呢变了。这个正的128呢,把它强转成是个败类型,竟然发现它是一个负128。这个过程呢,我觉得应该不用给大家花这个太多的精力去解释这个事儿了,那就简单来看一下,我这呢是整了一个计算器,咱这个数据呢是128,一共是32位,对吧,现在呢,我们把它转换成是个BY类型,把高位砍掉,只保留这一块。
12:02
只保留这一块的话呢,你看最高位就是一了,所以它就变成了负数了,而这个负数呢,恰好就是咱们的负128。啊,就是这样一个道理啊,行这个呢,我们就把这个金融损失这块呢,给大家介绍一下。然后再往下这块呢,有一个特殊的这个补充说明,因为对于咱们说这个数值类型这块呢,有两个比较特殊的情况。有两个比较特殊的情况,一个呢叫做na not number,这个咱们前面呢也提到过这个问题就是不确定的,它这个值到底是多少,另外一个呢,就涉及到这种无限的大小。这个在在哪写了。嗯,好,在这儿写的是吧,这个接近于这个无限大infinity是吧,那这个时候呢,我们该如何去处理这呢,就提到了这个官方遵循的这个协议里边这个规范了,咱们看一下。说当将一个浮点值转化成一个整数值的时候,整数可能是int,也可能是long,对吧?遵循的规则,这个浮点值呢,如果是na,那么转化成int或者long呢?因为它是一个不确定的值,对于整形咱们没有这个na的这个取值,那这时候转换过来是几啊,这块注意是零。
13:13
注意这块是零,那下边说如果浮点值不是无穷大的话,不是无穷大,那按照这个规则呢,那我们就该舍的就舍就完了,在这个范围之内,我们取这个,尽可能能取到这个最大值就行。就行对吧,然后下边呢,涉及到这个double跟往这个float类型在转的时候,那有可能这个double呢,咱们知道它表示的精度呢,是比较精确的,那转化的过程当中,假设你转这个值呢,绝对值特别小,言外之意就是离这个数轴。这个我们是一个数值的话呢,是零吧,对吧,那精度呢,大部类型精度这个更高,它那离这个零呢,就是绝对值更小,就是离这个零更近呗,啊进到了我们这个float呢,它都没办法来表示了,那这个时候呢,我们这个返回的这个值呢,就要正负零了。就是相当于因为你精度没那么高了嘛,绝对值太小,它精度没那么高,那就按相当于零来进行处理,那如果转化以后的这个绝对值太大了,毕竟人家这个double呢,可以表示的负负的数或者极大的这个数比你这个float呢更更广嘛,是吧,那这时候呢,比你超出你这个float可以表示的特别小或者特别大的,就说怎么办呢?那就返回你float的那个正负无穷大。
14:22
正负无穷大对吧,那如果呢,把double类型的na转换成float类型的,那就还是na。这个我觉得一说大家应该能够理解理解,别蒙啊,这个别蒙他不难来,那过来我们再通过这个例子呢,给大家测试一下。下边呢,我写了先这个代码。咱们来测试一下这个na是吧,还有呢,咱们说这个无穷大的这个情况。行,那这块呢,咱们来看这个例子,嗯,这里边的话,你看我定义一个double类型的叫na na是吧,Double类型或者你写个float类型都行,这呢我是以double为例来说的,它表示一个不确定的值。
15:04
还可以呢,比如说给大家举个例子,就是你拿这个,呃,这个比如说0.0去除以个0.0,这个结果呢,它就是一个na啊,这个结果就是na,因为咱们前面也给大家举过例子,这个结果是几,咱们其实不好说对吧,行。这个叫note number,然后这这个呢,得到叫第一,那咱们也可以在这儿,你保险起见,你可以输出一下,你看这个第一到底是什么,这个呢,咱们暂时先注释掉。把这个呢跑一下。你看这个呢,是n nan没问题的,对吧,现在呢,我们将这个n na的这个值呢,付给一个int型的值,或者你付一个long也是一样的,只要付给整形的话呢,我们说整形是不存在这个na的这个情况的,那你付过来怎么办呢?我们说就按照这个零去处理。是不是你在这写的就按照这个零来进行处理,OK啊,这就我们说的这个问题行。然后下面呢,咱们来说一下这个无穷大的这个问题。
16:02
无穷大的问题,我这个呢,是一个正的无穷大。那相应的这也有对应的,这个叫负的无穷大,这个叫positive infinity,那还有这个呢,叫negative INF infinity,那对应的就是一个负的无穷大,对吧?行,那这样,比如说我们取一个叫正的无穷大,一个正的无穷大的这个数。这个数呢,我们现在把它转化成是一个long类型,把它转换成是一个int类型,诶这个转化成结果变成什么呢?很显然这个double无穷大呢,比我们浪和int的范围是不是要更广一些啊。对吧,更广一些,那这个结果呢,哎,跑一下。好,这是我们看到这个结果呢,这个long类型的是它,然后int类型的是它,这两个数的话呢,大家可能没有概念对吧,没有概念,那这里边儿呢,我再给你打印两个值你就知道了,Long有一个叫max value。这个in特类型呢,我们对应的整形呢叫特了,对吧,In呢也有一个max value,就是各自呢能取到的最大值,来咱们再做一个执行。
17:10
好,这个时候呢,大家你会发现这两个数是不是一样,这两个数是不是也一样,那好了,这个结果我们就出来了,也就是说当你是浮电型的这个最取到无穷大的,这个时候呢,我们这个对于这个浪类型或硬的类型来讲,那我们就尽量的也取我这儿。范围之内的最大值跟你去匹配。那相应的,如果要是咱们把这个值,大家应该这也能理解,把这个double型的这个所谓的正的无穷大值,我转换成float的类型,那是不是也尽可能的我们要取到float的类型的一个。最大值对吧,那你看我我这改成个第二线啊,那float这个无穷大这个值是多少呢?注意float类型的无穷大它也是一个叫infinity来表示的啊,没有具体的,像我们说int型或者long类型给它具体标识出来了啊,这个大家要注意一下这个问题,行,那刚才我这块呢,写的是一个这个第一是吧。
18:04
或者改成是F1F1啊,这个改成是个D1,这块想说明的问题是啥呢?就是如果呢,你这个double类型呢,是一个na,我们把这个na呢转换成一个float的类型,你long double呢是不确定的,那转换成float的类型是不是也是不确定的呀。也是na对吧,哎,OK,没有问题,行,那咱们刚才呢,解释的这个na和无穷大呢,其实主要呢,针对于是我们这个补充说明里边的这几个点展开的这个大家呢,这个就是干记这个东西呢,没有意义,就是其实是可以通过理解的方式呢,咱们把这个事儿呢,只要理解清楚了,当然呢,你再去处理这个问题的时候呢,就不会出问题。好,那这样的话呢,咱们就把这个窄化类型转化呢,就也说清楚了。
我来说两句