1.Java數(shù)據(jù)類型基本概念: 數(shù)據(jù)類型在計算機語言里面,是對內(nèi)存位置的一個抽象表達(dá)方式,可以理解為針對內(nèi)存的一種抽象的表達(dá)方式。接觸每種語言的時候,都會存在數(shù)據(jù)類型的認(rèn)識,有復(fù)雜的、簡單的,各種數(shù)據(jù)類型都需要在學(xué)習(xí)初期去了解,Java是強類型語言,所以Java對于數(shù)據(jù)類型的規(guī)范會相對嚴(yán)格。數(shù)據(jù)類型是語言的抽象原子概念,可以說是語言中最基本的單元定義,在Java里面,本質(zhì)上講將數(shù)據(jù)類型分為兩種:簡單類型和復(fù)雜類型。 簡單類型:簡單數(shù)據(jù)類型是不能簡化的、內(nèi)置的數(shù)據(jù)類型、由編程語言本身定義,它表示了真實的數(shù)字、字符和整數(shù)。 復(fù)雜類型:Java語言本身不支持C++中的結(jié)構(gòu)(struct)或聯(lián)合(union)數(shù)據(jù)類型,它的復(fù)合數(shù)據(jù)類型一般都是通過類或接口進行構(gòu)造,類提供了捆綁數(shù)據(jù)和方法的方式,同時可以針對程序外部進行信息隱藏。 2.Java中的基本類型: 1)概念: Java中的簡單類型從概念上分為四種:實數(shù)、整數(shù)、字符、布爾值。但是有一點需要說明的是,Java里面只有八種原始類型,其列表如下: 實數(shù):double、float 整數(shù):byte、short、int、long 字符:char 布爾值:boolean 復(fù)雜類型和基本類型的內(nèi)存模型本質(zhì)上是不一樣的,簡單數(shù)據(jù)類型的存儲原理是這樣的:所有的簡單數(shù)據(jù)類型不存在“引用”的概念,簡單數(shù)據(jù)類型都是直接存儲在內(nèi)存中的內(nèi)存棧上的,數(shù)據(jù)本身的值就是存儲在??臻g里面,而Java語言里面只有這八種數(shù)據(jù)類型是這種存儲模型;而其他的只要是繼承于Object類的復(fù)雜數(shù)據(jù)類型都是按照Java里面存儲對象的內(nèi)存模型來進行數(shù)據(jù)存儲的,使用Java內(nèi)存堆和內(nèi)存棧來進行這種類型的數(shù)據(jù)存儲,簡單地講,“引用”是存儲在有序的內(nèi)存棧上的,而對象本身的值存儲在內(nèi)存堆上的。 2)詳細(xì)介紹: Java的簡單數(shù)據(jù)講解列表如下: int:int為整數(shù)類型,在存儲的時候,用4個字節(jié)存儲,范圍為-2,147,483,648到2,147,483,647,在變量初始化的時候,int類型的默認(rèn)值為0。 short:short也屬于整數(shù)類型,在存儲的時候,用2個字節(jié)存儲,范圍為-32,768到32,767,在變量初始化的時候,short類型的默認(rèn)值為0,一般情況下,因為Java本身轉(zhuǎn)型的原因,可以直接寫為0。 long:long也屬于整數(shù)類型,在存儲的時候,用8個字節(jié)存儲,范圍為-9,223,372,036,854,775,808到9,223,372,036, 854,775,807,在變量初始化的時候,long類型的默認(rèn)值為 byte:byte同樣屬于整數(shù)類型,在存儲的時候,用1個字節(jié)來存儲,范圍為-128到127,在變量初始化的時候,byte類型的默認(rèn)值也為0。 float:float屬于實數(shù)類型,在存儲的時候,用4個字節(jié)來存儲,范圍為32位IEEEE 754單精度范圍,在變量初始化的時候,float的默認(rèn)值為 double:double同樣屬于實數(shù)類型,在存儲的時候,用8個字節(jié)來存儲,范圍為64位IEEE 754雙精度范圍,在變量初始化的時候,double的默認(rèn)值為0.0。 char:char屬于字符類型,在存儲的時候用2個字節(jié)來存儲,因為Java本身的字符集不是用ASCII碼來進行存儲,是使用的16位Unicode字符集,它的字符范圍即是Unicode的字符范圍,在變量初始化的時候,char類型的默認(rèn)值為'u0000'。 boolean:boolean屬于布爾類型,在存儲的時候不使用字節(jié),僅僅使用1位來存儲,范圍僅僅為0和1,其字面量為true和false,而boolean變量在初始化的時候變量的默認(rèn)值為false。 3)相關(guān)介紹: 在Java基本類型在使用字面量賦值的時候,有幾個簡單的特性如下: 【1】當(dāng)整數(shù)類型的數(shù)據(jù)使用字面量賦值的時候,默認(rèn)值為int類型,就是直接使用0或者其他數(shù)字的時候,值的類型為int類型,所以當(dāng)使用long a = 0這種賦值方式的時候,JVM內(nèi)部存在數(shù)據(jù)轉(zhuǎn)換。 【2】當(dāng)實數(shù)類型的數(shù)據(jù)使用字面量賦值的時候,默認(rèn)值為double類型,就是當(dāng)字面兩出現(xiàn)的時候,JVM會使用double類型的數(shù)據(jù)類型。 ?。?/SPAN>*:以上兩點在轉(zhuǎn)型中進行詳細(xì)說明。) 【3】從JDK 5.0開始,Java里面出現(xiàn)了自動拆箱解箱的操作,基于這點需要做一定的說明: 對應(yīng)原始的數(shù)據(jù)類型,每種數(shù)據(jù)類型都存在一個復(fù)雜類型的封裝類,分別為Boolean、Short、Float、Double、Byte、Int、Long、Character,這些類型都是內(nèi)置的封裝類,這些封裝類(Wrapper)提供了很直觀的方法,針對封裝類需要說明的是,每種封裝類都有一個xxxValue()的方法,通過這種方法可以把它引用的對象里面的值轉(zhuǎn)化成為原始變量的值,不僅僅如此,每個封裝類都還存在一個valueOf(String)的方法直接把字符串對象轉(zhuǎn)換為相應(yīng)的簡單類型。 在JDK 5.0之前,沒有存在自動拆解箱的操作,即Auto Box操作,所以在這之前是不能使用以下方式的賦值代碼的: Integer a = 0; //這種賦值方式不能夠在JDK 1.4以及以下的JDK編譯器中通過 但是JDK 5.0出現(xiàn)了自動拆解箱的操作,所以在JDK 5.0以上的編譯器中,以上的代碼是可以通過的,關(guān)于自動拆箱解箱我會另外用一篇1.4到5.0的升級加以詳細(xì)說明。 3.Java中簡基本數(shù)據(jù)類型的轉(zhuǎn)型: Java中的簡單數(shù)據(jù)類型的轉(zhuǎn)換分為兩種:自動轉(zhuǎn)換和強制轉(zhuǎn)換 1)自動轉(zhuǎn)換: 當(dāng)一個較“小”的數(shù)據(jù)和較“大”的數(shù)據(jù)一起運算的時候,系統(tǒng)將自動將較“小”的數(shù)據(jù)轉(zhuǎn)換為較“大”的數(shù)據(jù),再進行運算。 在方法調(diào)用過程,如果實際參數(shù)較“小”,而函數(shù)的形參比較“大”的時候,除非有匹配的方法,否則會直接使用較“大”的形參函數(shù)進行調(diào)用。 2)強制轉(zhuǎn)換: 將“大”數(shù)據(jù)轉(zhuǎn)換為“小”數(shù)據(jù)時,可以使用強制類型轉(zhuǎn)換,在強制類型轉(zhuǎn)換的時候必須使用下邊這種語句: int a = (int)3.14; 只是在上邊這種類型轉(zhuǎn)換的時候,有可能會出現(xiàn)精度損失。 關(guān)于類型的自動提升,遵循下邊的規(guī)則: 所有的byte、short、char類型的值將提升為int類型; 如果有一個操作數(shù)是long類型,計算結(jié)果是long類型; 如果有一個操作數(shù)是float類型,計算結(jié)果是float類型; 如果有一個操作數(shù)是double類型,計算結(jié)果是double類型; 自動類型轉(zhuǎn)換圖如下: byte->short(char)->int->long->float->double 如果是強制轉(zhuǎn)換的時候,就將上邊的圖反過來 3)轉(zhuǎn)換附加: 當(dāng)兩個類型進行自動轉(zhuǎn)換的時候,需要滿足條件:【1】這兩種類型是兼容的,【2】目的類型的數(shù)值范圍應(yīng)該比源轉(zhuǎn)換值的范圍要大。而拓展范圍就遵循上邊的自動類型轉(zhuǎn)換樹,當(dāng)這兩個條件都滿足的時候,拓展轉(zhuǎn)換才會發(fā)生,而對于幾個原始類型轉(zhuǎn)換過程,根據(jù)兼容性boolean和char應(yīng)該是獨立的,而其他六種類型是可以兼容的,在強制轉(zhuǎn)換過程,唯獨可能特殊的是char和int是可以轉(zhuǎn)換的,不過會使用char的ASCII碼值比如: int a = (int)'a'; a的值在轉(zhuǎn)換過后輸出的話,值為97; 4.Java中的高精度數(shù): Java提供了兩個專門的類進行高精度運算:BigInteger與BigDecimal,雖然Java原始變量都具有對應(yīng)的封裝類型,但是這兩個變量沒有對應(yīng)的原始類型,而是通過方法來提供這兩種類型的一些運算,其含義為普通類型能夠做的操作,這兩個類型對應(yīng)都有,只是因為精度過大可能效率不夠高。至于這兩個類的具體操作可以參考JDK的相關(guān)API文檔。 5.關(guān)于數(shù)據(jù)類型的一些技巧:(以下為參考一篇原文文檔) 若要求精度的結(jié)果,盡量避免使用float和double: float和double類型本身是為了做科學(xué)運算,即執(zhí)行二進制浮點運算而設(shè)計,但是卻不能提供完全精確的結(jié)果,所以在要求精度的數(shù)值中,避免使用float和double,float和double在貨幣運算中尤其不合適,要讓float和double精確表達(dá)0.1也是不可能的事。測試一下下邊這段代碼就明白了: System.out.println(2.02-0.42); 結(jié)果是不是出乎意料,這個結(jié)果并不是偶然,而是JVM本身設(shè)計的目的決定的。而要解決這個問題,最好的辦法是使用BigDecimal、int或者long進行相關(guān)運算,特別是貨幣運算,使用BigDecimal代替double是一個很好的辦法。 BigDecimal唯一的缺點在于:BigDecimal沒有相對應(yīng)的原始類型,所以在進行基本數(shù)值運算的時候,需要進行方法調(diào)用才能操作,這樣會使得和我們的編程習(xí)慣不相符合,若使用int和long,就需要進行簡單的封裝運算。 所以在要求精度答案的計算任務(wù)里面,一般慎用float和double,如果在進行商務(wù)運算,并且要求四舍五入或者簡單的舍入行為,使用BigDecimal可能更加方便。所以盡量避免在精度運算中使用float和double,特別是我們常用的貨幣運算。 |
|