日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 类型转换_java中的基本数据类型的转换

發(fā)布時間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 类型转换_java中的基本数据类型的转换 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文參考了如下兩篇文章:

Java中,經(jīng)常可以遇到類型轉(zhuǎn)換的場景,從變量的定義到復(fù)制、數(shù)值變量的計算到方法的參數(shù)傳遞、基類與派生類間的造型等,隨處可見類型轉(zhuǎn)換的身影。Java中的類型轉(zhuǎn)換在Java編碼中具有重要的作用。

首先,來了解下數(shù)據(jù)類型的基本理解:數(shù)據(jù)是用來描述數(shù)據(jù)的種類,包括其值和基于其值基礎(chǔ)上的可進行的操作集合。

Java中數(shù)據(jù)類型主要分為兩大類:基本數(shù)據(jù)類型和引用數(shù)據(jù)類型。

基本數(shù)據(jù)類型共有8種,分別是:布爾型boolean, 字符型char和數(shù)值型byte/short/int/long/float/double。由于字符型char所表示的單個字符與Ascii碼中相應(yīng)整形對應(yīng),因此,有時也將其劃分到數(shù)值型中。引用類型具體可分為:數(shù)組、類和接口。因此java中類型的轉(zhuǎn)化分為基本數(shù)據(jù)類型的轉(zhuǎn)換和引用數(shù)據(jù)類型的轉(zhuǎn)換,本文將針對基本數(shù)據(jù)類型的轉(zhuǎn)換進行總結(jié).

1.基本數(shù)據(jù)類型的類型轉(zhuǎn)換

數(shù)據(jù)類型

所占字節(jié)

boolean

未定

byte

1字節(jié)

char

2字節(jié)

short

2字節(jié)

int

4字節(jié)

long

8字節(jié)

float

4字節(jié)

double

8字節(jié)

從上表可以看出java中各種數(shù)據(jù)類型所占空間的大小. 在java中整數(shù)的默認數(shù)據(jù)類型是int, 例如數(shù)字4, 小數(shù)的默認數(shù)字類型是double, 例如3.12. 當(dāng)float a = 3.12時會報錯, 因為3.12的默認數(shù)據(jù)類型是double, 我們需要使用如下的賦值方法:

第一種方法在3.12后面加了一個F, 告訴編譯器這是一個float的數(shù). 第二種方法對3.12進行了強制的類型轉(zhuǎn)換. 接下來我們仔細分析一下java中的類型轉(zhuǎn)換問題.

基本數(shù)據(jù)類型中,布爾類型boolean占有一個字節(jié),由于其本身所代碼的特殊含義,boolean類型與其他基本類型不能進行類型的轉(zhuǎn)換(既不能進行自動類型的提升,也不能強制類型轉(zhuǎn)換), 否則,將編譯出錯。

a. 基本數(shù)據(jù)類型中類型的自動提升

數(shù)值類型在內(nèi)存中直接存儲其本身的值,對于不同的數(shù)值類型,內(nèi)存中會分配相應(yīng)的大小去存儲。如:byte類型的變量占用8位,int類型變量占用32位等。相應(yīng)的,不同的數(shù)值類型會有與其存儲空間相匹配的取值范圍。具體如下所示:

圖中依次表示了各數(shù)值類型的字節(jié)數(shù)和相應(yīng)的取值范圍。在Java中,整數(shù)類型(byte/short/int/long)中,對于未聲明數(shù)據(jù)類型的整形,其默認類型為int型。在浮點類型(float/double)中,對于未聲明數(shù)據(jù)類型的浮點型,默認為double型。

看下面的例子

??

是不是有點奇怪?按照上面的思路去理解,將一個int型的1000賦給一個byte型的變量a,提示出錯,但是最后一句:將一個int型的3賦給一個byte型的變量c,居然編譯正確,這是為什么呢?

原因在于:jvm在編譯過程中,對于默認為int類型的數(shù)值時,當(dāng)賦給一個比int型數(shù)值范圍小的數(shù)值類型變量(在此統(tǒng)一稱為數(shù)值類型k,k可以是byte/char/short類型),會進行判斷,如果此int型數(shù)值超過數(shù)值類型k,那么會直接編譯出錯。因為你將一個超過了范圍的數(shù)值賦給類型為k的變量,k裝不下嘛,你有沒有進行強制類型轉(zhuǎn)換,當(dāng)然報錯了。但是如果此int型數(shù)值尚在數(shù)值類型k范圍內(nèi),jvm會自定進行一次隱式類型轉(zhuǎn)換,將此int型數(shù)值轉(zhuǎn)換成類型k。如圖中的虛線箭頭。這一點有點特別,需要稍微注意下。

另外在IDEA中, 類型的判斷會在寫程序時由編輯器幫你做判斷, 而不需要到編譯的時候由編譯器來做判斷, 這也是IDEA的一個優(yōu)點.

在其他情況下,當(dāng)將一個數(shù)值范圍小的類型賦給一個數(shù)值范圍大的數(shù)值型變量,jvm在編譯過程中俊將此數(shù)值的類型進行了自動提升。在數(shù)值類型的自動類型提升過程中,數(shù)值精度至少不應(yīng)該降低(整型保持不變,float->double精度將變高)。

?

如上:定義long類型的a變量時,將編譯出錯,原因在于11111111111默認是int類型,同時int類型的數(shù)值范圍是-2^31 ~ 2^31-1,因此,11111111111已經(jīng)超過此范圍內(nèi)的最大值,故而其自身已經(jīng)編譯出錯,更談不上賦值給long型變量a了。

此時,若想正確賦值,改變11111111111自身默認的類型即可,直接改成11111111111L即可將其自身類型定義為long型。此時再賦值編譯正確。

將值為10的int型變量 z 賦值給long型變量q,按照上文所述,此時直接發(fā)生了自動類型提升, 編譯正確。

接下來,還有一個地方需要注意的是:char型其本身是unsigned型,同時具有兩個字節(jié),其數(shù)值范圍是0 ~ 2^16-1,因為,這直接導(dǎo)致byte型不能自動類型提升到char,char和short直接也不會發(fā)生自動類型提升(因為負數(shù)的問題),同時,byte當(dāng)然可以直接提升到short型。

b. 隱式類型轉(zhuǎn)換

上面的例子中既有隱式類型轉(zhuǎn)換, 也有強制類型轉(zhuǎn)換, 那么什么是隱式類型轉(zhuǎn)換呢?

隱式轉(zhuǎn)換也叫作自動類型轉(zhuǎn)換, 由系統(tǒng)自動完成.

從存儲范圍小的類型到存儲范圍大的類型.

byte ->short(char)->int->long->float->double

c. 顯示類型轉(zhuǎn)換

顯示類型轉(zhuǎn)換也叫作強制類型轉(zhuǎn)換, 是從存儲范圍大的類型到存儲范圍小的類型.

當(dāng)我們需要將數(shù)值范圍較大的數(shù)值類型賦給數(shù)值范圍較小的數(shù)值類型變量時,由于此時可能會丟失精度(1講到的從int到k型的隱式轉(zhuǎn)換除外),因此,需要人為進行轉(zhuǎn)換。我們稱之為強制類型轉(zhuǎn)換。

double→float→long→int→short(char)→byte

byte a =3;編譯正確在1中已經(jīng)進行了解釋。接下來將一個值為3的int型變量b賦值給byte型變量c,發(fā)生編譯錯誤。這兩種寫法之間有什么區(qū)別呢?

區(qū)別在于前者3是直接量,編譯期間可以直接進行判定,后者b為一變量,需要到運行期間才能確定,也就是說,編譯期間為以防萬一,當(dāng)然不可能編譯通過了。此時,需要進行強制類型轉(zhuǎn)換。

強制類型轉(zhuǎn)換所帶來的結(jié)果是可能會丟失精度,如果此數(shù)值尚在范圍較小的類型數(shù)值范圍內(nèi),對于整型變量精度不變,但如果超出范圍較小的類型數(shù)值范圍內(nèi),很可能出現(xiàn)一些意外情況。

上面的例子中輸出值是 -23.

為什么結(jié)果是-23?需要從最根本的二進制存儲考慮。

233的二進制表示為:24位0 + 11101001,byte型只有8位,于是從高位開始舍棄,截斷后剩下:11101001,由于二進制最高位1表示負數(shù),0表示正數(shù),其相應(yīng)的負數(shù)為-23。

d.?進行數(shù)學(xué)運算時的數(shù)據(jù)類型自動提升與可能需要的強制類型轉(zhuǎn)換

當(dāng)進行數(shù)學(xué)運算時,數(shù)據(jù)類型會自動發(fā)生提升到運算符左右之較大者,以此類推。當(dāng)將最后的運算結(jié)果賦值給指定的數(shù)值類型時,可能需要進行強制類型轉(zhuǎn)換。例如:

a+b會自動提升為int, 因此在給c賦值的時候要強制轉(zhuǎn)換成byte.

2.類型轉(zhuǎn)換中的符號擴展Sign Extension

有沒有想過這么一個問題, 當(dāng)把一個byte的負數(shù)轉(zhuǎn)換為int時, 它的值是正數(shù)還是負數(shù)呢? 當(dāng)把一個int強制轉(zhuǎn)為為byte, 我們能否確定轉(zhuǎn)換后數(shù)字的符號呢? 要理解這兩點, 我們首先要明白計算機中數(shù)的表示, 和java中類型轉(zhuǎn)換時進行的操作.

a. 計算機中數(shù)的表示

計算機中的數(shù)都是以補碼的形式存儲的, 最高位是符號位. 正數(shù)的補碼是它本身, 而負數(shù)的補碼是原碼按位取反后加1. 這樣我們就很清楚java中這些數(shù)據(jù)類型的范圍是怎么得到的.

例如: byte的范圍是-128 ~ 127. 為什么會有-128呢? 其實-128的二進制表示是 10000000, 這個補碼形式是不是很奇怪呢? 我們找不到一個數(shù)可以對應(yīng)這樣的補碼, 其實這是-0的原碼, 那-0的補碼呢? 按位取反加1試試看, 是不是又變?yōu)?0000000呢? 所以這個多出來的-0就用來表示-128了.

有了上面的表示, 我們就要問: 如何在類型擴展的時候保持數(shù)字的符號和值不變呢?

b. java中的符號擴展

1) 什么是符號擴展

符號擴展(Sign Extension)用于在數(shù)值類型轉(zhuǎn)換時擴展二進制位的長度,以保證轉(zhuǎn)換后的數(shù)值和原數(shù)值的符號(正或負)和大小相同,一般用于較窄的類型(如byte)向較寬的類型(如int)轉(zhuǎn)換。擴展二進制位長度指的是,在原數(shù)值的二進制位左邊補齊若干個符號位(0表示正,1表示負)。

舉例來說,如果用6個bit表示十進制數(shù)10,二進制碼為"00 1010",如果將它進行符號擴展為16bits長度,結(jié)果是"0000 0000 0000 1010",即在左邊補上10個0(因為10是正數(shù),符號為0),符號擴展前后數(shù)值的大小和符號都保持不變;如果用10bits表示十進制數(shù)-15,使用“2的補碼”編碼后,二進制碼為"11 1111 0001",如果將它進行符號擴展為16bits,結(jié)果是"1111 1111 1111 0001",即在左邊補上6個1(因為-15是負數(shù),符號為1),符號擴展前后數(shù)值的大小和符號都保持不變。

2) java中數(shù)值類型轉(zhuǎn)換的規(guī)則

這個規(guī)則是《Java解惑》總結(jié)的:如果最初的數(shù)值類型是有符號的,那么就執(zhí)行符號擴展;如果是char類型,那么不管它要被轉(zhuǎn)換成什么類型,都執(zhí)行零擴展。還有另外一條規(guī)則也需要記住,如果目標(biāo)類型的長度小于源類型的長度,則直接截取目標(biāo)類型的長度。例如將int型轉(zhuǎn)換成byte型,直接截取int型的右邊8位。

所以java在進行類型擴展時候會根據(jù)原始數(shù)據(jù)類型, 來執(zhí)行符號擴展還是零擴展. 數(shù)值類型轉(zhuǎn)數(shù)值類型的符號擴展不會改變值的符號和大小.

c.?解析“多重轉(zhuǎn)型”問題

一個連續(xù)三次類型轉(zhuǎn)換的表達式如下:

1. int(32位) -> byte(8位)

-1是int型的字面量,根據(jù)“2的補碼”編碼規(guī)則,編碼結(jié)果為0xffffffff,即32位全部置1.轉(zhuǎn)換成byte類型時,直接截取最后8位,所以byte結(jié)果為0xff,對應(yīng)的十進制值是-1.

2. byte(8位)-> char(16位)

由于byte是有符號類型,所以在轉(zhuǎn)換成char型(16位)時需要進行符號擴展,即在0xff左邊連續(xù)補上8個1(1是0xff的符號位),結(jié)果是0xffff。由于char是無符號類型,所以0xffff表示的十進制數(shù)是65535。

3. char(16位)-> int(32位)

由于char是無符號類型,轉(zhuǎn)換成int型時進行零擴展,即在0xffff左邊連續(xù)補上16個0,結(jié)果是0x0000ffff,對應(yīng)的十進制數(shù)是65535。

d. 幾個轉(zhuǎn)型的例子

在進行類型轉(zhuǎn)換時,一定要了解表達式的含義,不能光靠感覺。最好的方法是將你的意圖明確表達出來。

在將一個char型數(shù)值c轉(zhuǎn)型為一個寬度更寬的類型時,并且不希望有符號擴展,可以如下編碼:

上文曾提到過,0xffff是int型字面量,所以在進行&操作之前,編譯器會自動將c轉(zhuǎn)型成int型,即在c的二進制編碼前添加16個0,然后再和0xffff進行&操作,所表達的意圖是強制將前16置0,后16位保持不變。雖然這個操作不是必須的,但是明確表達了不進行符號擴展的意圖。

如果需要符號擴展,則可以如下編碼:

首先將c轉(zhuǎn)換成short類型,它和char是?等寬度的,并且是有符號類型,再將short類型轉(zhuǎn)換成int類型時,會自動進行符號擴展,即如果short為負數(shù),則在左邊補上16個1,否則補上16個0.

如果在將一個byte數(shù)值b轉(zhuǎn)型為一個char時,并且不希望有符號擴展,那么必須使用一個位掩碼來限制它:

(b & 0xff)的結(jié)果是32位的int類型,前24被強制置0,后8位保持不變,然后轉(zhuǎn)換成char型時,直接截取后16位。這樣不管b是正數(shù)還是負數(shù),轉(zhuǎn)換成char時,都相當(dāng)于是在左邊補上8個0,即進行零擴展而不是符號擴展。

如果需要符號擴展,則編碼如下:

此時為了明確表達需要符號擴展的意圖,注釋是必須的。

e.總結(jié)

實際上在數(shù)值類型轉(zhuǎn)換時,只有當(dāng)遇到負數(shù)時才會出現(xiàn)問題,根本原因就是Java中的負數(shù)不是采用直觀的方式進行編碼,而是采用“2的補碼”方式,這樣的好處是加法和減法操作可以同時使用加法電路完成,但是在開發(fā)時卻會遇到很多奇怪的問題,例如(byte)128的結(jié)果是-128,即一個大的正數(shù),截斷后卻變成了負數(shù)。3.2節(jié)中引用了一些轉(zhuǎn)型規(guī)則,應(yīng)用這些規(guī)則可以很容地解決常見的轉(zhuǎn)型問題。

參考引用

3. Joshua Bloch, 陳昊鵬譯 - 《Java解惑》

總結(jié)

以上是生活随笔為你收集整理的java 类型转换_java中的基本数据类型的转换的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。