Java 數(shù)據(jù)類型(全網(wǎng)最全)

數(shù)據(jù)類型方法論

程序本質(zhì)上是對(duì)數(shù)據(jù)的處理(邏輯運(yùn)算),因此任何語言都需先解決如何表征【數(shù)據(jù)】這個(gè)核心概念。數(shù)據(jù)作為抽象的概念,天然的包含2個(gè)方面屬性:

  • 類型:類型決定了數(shù)據(jù)只能和同類型的數(shù)據(jù)進(jìn)行運(yùn)算才有意義,不同類型的數(shù)據(jù)必須進(jìn)行類型轉(zhuǎn)換
  • 數(shù)值:是數(shù)據(jù)的數(shù)學(xué)意義上的大小或內(nèi)容。

同時(shí)數(shù)據(jù)保存在內(nèi)存或磁盤中,總是占用一定的存儲(chǔ)空間,因此一個(gè)數(shù)據(jù)在程序中是由類型、數(shù)值存儲(chǔ)空間表示的。

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

Java 是一種強(qiáng)類型語言,每個(gè)變量在聲明時(shí)必須指定其數(shù)據(jù)類型。根據(jù)參數(shù)傳遞時(shí)的賦值方式,Java 中的數(shù)據(jù)類型分2類:

基本數(shù)據(jù)類型(值類型)

參數(shù)傳遞時(shí)總是以值拷貝的形式,賦值給接收變量。

本質(zhì)是對(duì)數(shù)學(xué)意義上的純數(shù)值類數(shù)據(jù)的抽象,因此又叫值類型.

注意: 基本數(shù)據(jù)類型在語言層面是不可分割的基本單元,但硬件層面并非是不可分割的,因?yàn)閮?nèi)存的讀寫是以內(nèi)存行(64位)為基本單位的,占用2個(gè)或2個(gè)以上內(nèi)存行的數(shù)據(jù)在高并發(fā)下是不安全的。

java-basic-assign.png

引用類型

即參數(shù)傳遞時(shí)是以拷貝引用地址的方式傳遞給接收變量,而非復(fù)制整個(gè)"數(shù)據(jù)"本體。

除了基本數(shù)據(jù)類型外的、其他結(jié)構(gòu)化的數(shù)據(jù)類型,如字符串類型String、或自定義的類(如Person),本質(zhì)上是對(duì)現(xiàn)實(shí)世界結(jié)構(gòu)化、關(guān)系化數(shù)據(jù)的抽象,因?yàn)橐粋€(gè)對(duì)象(如人)總是具備多個(gè)特征屬性的,每個(gè)屬性都是一個(gè)基本數(shù)據(jù)類型。

為什么不是拷貝值?

這類類型的變量本質(zhì)上是一段存儲(chǔ)空間的起始地址,因?yàn)榻Y(jié)構(gòu)化數(shù)據(jù)的存儲(chǔ)空間的大小是由所有屬性疊加的,且是可變的,不能或很難實(shí)現(xiàn)原子性的拷貝,且空間代價(jià)很大,因此參數(shù)傳遞時(shí)并不是機(jī)械的拷貝所有屬性、所有空間,而是僅復(fù)制拷貝起始地址就行了,其他字段可以據(jù)此基地址和字段順序進(jìn)行偏移計(jì)算所得。

java-reference-assign.png

值類型和引用類型的區(qū)別

  • 概念方面

基本類型:變量名指向具體的數(shù)值,參數(shù)傳遞會(huì)拷貝值的副本,原值不受影響
引用類型:變量名指向存數(shù)據(jù)對(duì)象的內(nèi)存地址,參數(shù)傳遞是復(fù)制內(nèi)存段的起始地址,最終指向同一內(nèi)存段。

  • 相等語義

基本類型:使用時(shí)需要賦具體值,使用 == 號(hào)判斷值是否相等。
引用類型:== 是判斷引用地址是否相同;通常應(yīng)重寫 equals 方法實(shí)現(xiàn)自定義的邏輯,如同一學(xué)生會(huì)存在多個(gè)緩存中,重寫equals,根據(jù)學(xué)號(hào)no是否相等判斷是否是同一學(xué)生。

基本數(shù)據(jù)類型(值類型)

Java 語言共提供了4 類、8 種基本類型

java-value-type.png

整數(shù)型

是對(duì)數(shù)學(xué)中整數(shù)的表達(dá),按照數(shù)值范圍和存儲(chǔ)空間大小順序:byte < short < int < long

浮點(diǎn)型

是對(duì)數(shù)學(xué)中的小數(shù)的表達(dá),即有浮動(dòng)小數(shù)點(diǎn)的數(shù),

float - 32 位,直接賦值時(shí)必須在數(shù)字后加上 f 或 F,指示編譯器這是一個(gè)float型浮點(diǎn)數(shù)
double - 64 位,賦值時(shí)一般在數(shù)字后加 d 或 D,指示編譯器這是一個(gè)double型浮點(diǎn)數(shù)

Unicode 字符型

是對(duì)Unicode編碼的表達(dá),Unicode編碼是對(duì)全世界所有主要語言中各類字符、符號(hào)的編碼,是將文檔轉(zhuǎn)存成計(jì)算機(jī)的二進(jìn)制序列進(jìn)行保存的理論基礎(chǔ)。

char- 16 位,存儲(chǔ) Unicode 碼,用單引號(hào)賦值。

java-unicode.png
  • 可計(jì)算的

java 提供字符型,可以更方便的表述字符,同時(shí)支持基于編碼的數(shù)值計(jì)算,因此char類型的值本質(zhì)還是數(shù)值,可以參與數(shù)值計(jì)算。

布爾型(真假)

是對(duì)邏輯運(yùn)算值的表達(dá),即真True假False

boolean - 只有 true 和 false 兩個(gè)取值。

  • 非數(shù)值

boolean 類型是非數(shù)值類型的,因此和其他基本數(shù)據(jù)類型不能參與計(jì)算。

最小使用原則

即在滿足需求的前提下,優(yōu)先使用更小的類型,可以節(jié)省大量的內(nèi)存,提升程序的性能。Java每個(gè)大類都提高了多個(gè)大小不一的類型,即是靈活的需要,更是內(nèi)存優(yōu)化的需要。

類型轉(zhuǎn)換

正如方法論中所說,不同類型的數(shù)據(jù)不能直接混合計(jì)算,必須轉(zhuǎn)換同一種類型。

Java 中,數(shù)據(jù)類型轉(zhuǎn)換有兩種方式:自動(dòng)轉(zhuǎn)換強(qiáng)制轉(zhuǎn)換

自動(dòng)隱式轉(zhuǎn)換

在符合下面的規(guī)則下,Java編譯器會(huì)安全的、隱式的進(jìn)行轉(zhuǎn)換,降低用戶手動(dòng)轉(zhuǎn)換的壓力。

  • 自動(dòng)膨脹原則

即在精度不一致的混合場(chǎng)景下,Java編譯器會(huì)隱式的將精度較小的類型轉(zhuǎn)換成精度稍大的類型后才進(jìn)行計(jì)算,由小轉(zhuǎn)大,數(shù)據(jù)精度并不會(huì)丟失,因此是安全的。

膨脹的順序是:byte -> short/char -> int -> long -> float -> double

由下面的例子可以看出,Java編譯器不僅自動(dòng)優(yōu)化了變量類型,減少了內(nèi)存,而且自動(dòng)隱式的將 byte 轉(zhuǎn)換成了 float,整個(gè)表達(dá)式的最終結(jié)果已是float類型

java-int-auto.png

再使用精度較小的int型變量接收時(shí)就會(huì)提示出錯(cuò)。

java-int-float-error.png

強(qiáng)制轉(zhuǎn)換

在不符合自動(dòng)轉(zhuǎn)換條件時(shí)或者根據(jù)用戶的需要,可以使用符號(hào)()對(duì)數(shù)據(jù)類型做強(qiáng)制的轉(zhuǎn)換。

注意!?。。?/strong>從精度大到精度小的強(qiáng)制轉(zhuǎn)換,因?yàn)榇鎯?chǔ)空間也會(huì)縮小一半,因此存在數(shù)據(jù)出錯(cuò)的不確定性問題,用戶自身需要自我承擔(dān)這樣的風(fēng)險(xiǎn)。

可以看到雖然編譯階段是正常的,沒有提示錯(cuò)誤,但是運(yùn)行時(shí)的結(jié)果卻是一個(gè)不確定的數(shù)據(jù),而不是預(yù)期的。

java-force-convert-lost.png

裝箱和拆箱

為了基本數(shù)據(jù)類型可以與引用類型互相轉(zhuǎn)換,以利用彼此的特性,Java 為每一種基本數(shù)據(jù)類型提供了相應(yīng)的包裝(封裝)類。

java-basic-wrapper.png

包裝類和享元模式

Java基本數(shù)據(jù)類型的包裝類以value字段保留其對(duì)應(yīng)的數(shù)值,如Integer#value,可以通過構(gòu)造器或者valueof方法生成新的包裝對(duì)象實(shí)例。

  • 享元模式(即緩存池模式)

因?yàn)樵诙阎袆?chuàng)建新的對(duì)象是相對(duì)比較重的操作,同時(shí)基本數(shù)據(jù)類型的自動(dòng)裝箱又是程序中最常見的情況之一,因此為為避免重復(fù)創(chuàng)建這些常用的對(duì)象,Jdk實(shí)現(xiàn)的基本類型包裝類基本都會(huì)采用緩存池的設(shè)計(jì),即享元模式,數(shù)量由jvm參數(shù)XX:AutoBoxCacheMax指定。

饑餓池化 - 包裝類在首次加載時(shí)會(huì)對(duì)指定小范圍內(nèi)的數(shù)值進(jìn)行饑餓式池化,如java.lang.Integer.IntegerCache.high指定

懶加載池化 - 對(duì)每個(gè)首次使用的其他數(shù)值進(jìn)行懶加載池化和替換

享元模式是非常重要的設(shè)計(jì)模式一直,對(duì)內(nèi)存優(yōu)化和系統(tǒng)系統(tǒng)方面都是非常友好的。

java-integer-wrapper.png

裝箱(boxing)

即將基本數(shù)據(jù)類型轉(zhuǎn)換為對(duì)應(yīng)封裝類的引用類型,目的是獲得對(duì)應(yīng)封裝類的各類方法的能力。例如:int 轉(zhuǎn) Integer,編譯器是通過調(diào)用包裝類的 valueOf 方法實(shí)現(xiàn)的。

  • 自動(dòng)裝箱(auto boxing)

當(dāng)基本數(shù)據(jù)類型賦值給對(duì)應(yīng)包裝類的引用類型時(shí),Java會(huì)自動(dòng)的將基本數(shù)值類型通過其包裝類的valueOf,在堆上創(chuàng)建其對(duì)應(yīng)的包裝類對(duì)象。

java-auto-boxing.png

拆箱(unboxing)

是將封裝類的引用類型轉(zhuǎn)換為基本數(shù)據(jù)類型,例如:Integer 轉(zhuǎn) int,目的是可以參與常規(guī)的數(shù)學(xué)運(yùn)算。本質(zhì)是編譯器通過調(diào)用包裝類的 xxxValue 方法實(shí)現(xiàn)的。(xxx 代表對(duì)應(yīng)的基本數(shù)據(jù)類型)

  • 自動(dòng)拆箱(auto unboxing)

當(dāng)包裝類與基本數(shù)據(jù)類型混合運(yùn)算時(shí),Java會(huì)調(diào)用該包裝類的xxxValue獲得對(duì)應(yīng)的值類型的值,然后才參與表達(dá)式的計(jì)算。

java-auto-unboxing.png

總結(jié)

最后整理了一個(gè)完整的腦圖。

java數(shù)據(jù)類型.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容