對于一些中級的Java程式猿來說,經常會在面試的時候被問到資料類型轉換的問題,今天小千就整理了一些常見的關于資料類型的問題,同學們面試前提前看一下,做好準備呢。
一. Java資料類型
1. 概述
Java語言是靜态類型的(statical typed),也就是說所有變量和表達式的類型在編譯時就已經完全确定了。由于是statical typed,也就導緻了Java語言是強類型(Strong typed)的。強類型則意味着每個變量都屬于某一種類型,每個表達式也都屬于某一種類型,并且每種類型都是嚴格定義的。
而資料類型則限制了該變量可以存儲哪些值,表達式最終産生什麼值,同時限制了這些值可以進行的操作類型以及操作的具體方式。所有的指派操作,無論是顯式的還是在方法調用中通過參數傳遞的,都要進行類型的相容性檢查。
2. Java資料類型
Java的資料類型總體上分為兩大類,基本類型和引用類型!
2.1 基本類型(primitive type)
基本類型包括數值類型(numeric types)和布爾類型(boolean)。數值類型又分為整型(integer types)和浮點型(floating-point type),其中整型有5種:byte、short、int、long、char(char本質上是一種特殊的int);而浮點類型則包括float和double。
布爾類型的值隻有2個,也就是true和false。所有的基本類型都直接包含值(directly contain value)。
2.2 引用類型(reference type)
Java有 6種 引用類型(對象類型):類、接口、數組、枚舉、注解和null對象。
其中null是一種特殊的type,但是你不能聲明一個變量為null的類型,null type的唯一取值就是null。null可以指派給任意的引用類型或者轉化成任意的引用類型。在實踐中,一般把null當做字面值(literal),這個字面值可是是任意的引用類型。
3. 基本類型取值範圍
4. 引用類型間轉換規則
4.1 子類能直接轉換為父類 或 接口類型;
4.2 父類轉換為子類要強制類型轉換;且在運作時若實際不是對應的對象,會抛出ClassCastException運作時異常;
二. Java類型轉換
在Java中将一種類型的值賦給另一種類型是很常見的,其中boolean類型與所有其他7種類型都不能進行轉換,這一點很明确。對于其他7中數值類型,它們之間都可以進行轉換,但是可能會存在精度損失或者其他一些變化
1. 類型轉換方式
1.1 自動轉換(隐式轉換)
自動轉換時發生擴寬(widening conversion),因為較大的類型(如int)要儲存較小的類型(如byte),記憶體總是足夠的,不需要強制轉換。無需任何操作。
自動類型轉換特點: (1).兩種類型是彼此相容的;(2).轉換後的目标類型占的空間範圍一定要大于被轉化的源類型; (3).由低位元組向高位元組自動轉換(圖中黑線表示無資料丢失的自動資料轉換,紅線表示轉換中可能發生精度丢失)。
1.2 強制轉換(顯式轉換):需要顯式轉換,也就是需要使用轉換操作符。
如果要把大的轉成小的,或者在short與char之間進行轉換,就必須強制轉換,也被稱作縮小轉換(narrowing conversion),因為必須顯式地使數值更小以适應目标類型。強制轉換采用轉換操作符()。嚴格地說,将byte轉為char不屬于narrowing conversion),因為從byte到char的過程其實是byte-->int-->char,是以widening和narrowing都有。強制轉換除了可能的精度損失外,還可能使模(overall magnitude)發生變化。
将容納更多資訊的資料類型轉換成一個容量更小的資料類型,可能存在精度損失的風險,編譯器要求程式員進行強制類型轉換。而在強制轉換過程中可能會發生資料溢出,必須警惕。例如 int a=(int)3.14;
1.3 7種類型按範圍排序
byte <(short=char)< int < long < float < double
如果從小轉換到大,可以自動完成類型轉換,而從大到小,必須強制轉換。short和char兩種相同類型也必須強制轉換。
7種基本類型轉換總結如下圖:
三. 類型轉換面試題
1.short s = 1; s = s + 1;有沒有問題?如果有怎麼解決?short s = 1; s += 1;有沒有問題?如果有怎麼解決?
1) 對于short s1=1;s1=s1+1來說,在s1+1運算時會自動提升表達式的類型為int,那麼将int賦予給short類型的變量s1會出現類型轉換錯誤。
2) 對于short s1=1;s1+=1來說 +=是java語言規定的運算符,java編譯器會對它進行特殊處理,是以可以正确編譯。
2. char類型變量能不能儲存一個中文的漢字,為什麼?
char類型變量是用來儲存Unicode編碼的字元的,unicode字元集包含了漢字,是以char類型當然可以存儲漢字的,還有一種特殊情況就是某個生僻字沒有包含在unicode編碼字元集中,那麼就char類型就不能存儲該生僻字。
3. Integer和int的差別
int是java的8種内置的原始資料類型。Java為每個原始類型都提供了一個封裝類,Integer就是int的封裝類,int變量的預設值為0,Integer變量的預設值為null。
Integer類内提供了一些關于整數操作的一些方法,例如上文用到的表示整數的最大值和最小值。
4. switch語句能否作用在byte上,能否作用在long上,能否作用在string上?
byte的存儲範圍小于int,可以向int類型進行隐式轉換,是以switch可以作用在byte上;
long的存儲範圍大于int,不能向int進行隐式轉換,隻能強制轉換,是以switch不可以作用在long上;
switch()變量類型隻能是int、short、char、byte和enum類型;
case後面隻能是常量,可以是運算表達式,但一定要符合正确的類型。不能是變量,即便變量在之前進行了指派,JVM依然會報錯。
string在1.7版本之前不可以,1.7版本之後switch就可以作用在string上了。
5. float f1 = (float)11.11; float f2 = 11.11f; 這兩種定義資料有什麼不同嗎?
f1其實是通過一個double類型轉換過來的。而f2本身就是一個float類型。
6. byte b1=3, b2=4 , b ; b=b1+b2 ; b=3+4 ; 哪句是編譯失敗的呢?為什麼呢?
b = b1 + b2;會編譯失敗
因為當是變量相加時,會首先看類型,最終把結果指派的也會考慮類型問題。
常量相加,首先是先做加法,然後看結果是否在指派的資料類型範圍内,如果不是,才會報錯。
通過反編譯工具也會發現上面的代碼、會直接被編譯為(.class)