久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

面試中會遇到的15個易遺忘的Java問題

 白色楓車JAYCN 2016-06-22


導(dǎo)語

通常,,在面試中,會遇到面試官提一些比較“偏冷”的基礎(chǔ)知識,,比如基本數(shù)據(jù)類型所占用的字節(jié)數(shù),或者Unicode和UTF-8的區(qū)別之類的問題,,這時很多應(yīng)聘者會答錯,。還有在平常編碼的過程中,很多時候會用到除法計(jì)算,,比如對一個長度為100萬的List中的所有元素進(jìn)行除16的操作,,那么CPU對element<4操作的運(yùn)算會快于element>

因此,本文對一些容易被遺忘的基礎(chǔ)知識進(jìn)行歸納,,希望可以幫助廣大程序員輕松應(yīng)對面試官的基礎(chǔ)技術(shù)問題,,以及提升編碼效率。本文適合有一定Java基礎(chǔ)的技術(shù)人員閱讀,,部分內(nèi)容對初學(xué)者來說可能會比較吃力,。



1.Java中的基本數(shù)據(jù)類型以及所占內(nèi)存大小


(1)整形

byte    1字節(jié)

short    2字節(jié)

int    4字節(jié)

long    8字節(jié)


(2)浮點(diǎn)型

float    4字節(jié)

double    8字節(jié)


(3)字符類型

char    2字節(jié)(Unicode-16)


(4)布爾類型

布爾類型boolean比較特殊,盡管Java虛擬機(jī)定義了boolean類型,,但虛擬機(jī)對boolean類型的支持是有限的,,沒有為boolean值單獨(dú)設(shè)計(jì)JVM指令。操作布爾值的表達(dá)式在編譯之后,,它使用的是JVM的int數(shù)據(jù)類型,,也就是占用4個字節(jié)。


JVM也不會直接支持boolean數(shù)組,,boolean數(shù)組在編譯之后,,它的元素采用byte數(shù)據(jù)類型,用0表示false,,1表示true,,也就是boolean數(shù)組的元素只占用一個字節(jié)。


2.UTF-8與Unicode的關(guān)系


Unicode是一個統(tǒng)一的編碼標(biāo)準(zhǔn),,將現(xiàn)有的所有字符進(jìn)行唯一編碼,。在第一個Unicode版本中,使用兩個字節(jié)(16位)來表示一個字符,,注意這里的字節(jié)并非指的是計(jì)算機(jī)內(nèi)存中的存儲單元,,而是一個數(shù)學(xué)長度單位而已。然而,,一個Unicode字符在內(nèi)存中存儲所占用的長度,,就需要一個具體的編碼規(guī)則來實(shí)現(xiàn),比如UTF-8,。因此,,Unicode只是一個編碼標(biāo)準(zhǔn),而UTF-8是對這個標(biāo)準(zhǔn)的一個實(shí)現(xiàn),,UTF-8規(guī)定了一個Unicode字符在內(nèi)存中占用的空間(英文和中文所占空間是不同的,,有興趣的讀者可以查閱相關(guān)資料)。

代碼點(diǎn)指的是可以用于對字符集進(jìn)行編碼的那些數(shù)字,比如在16位的Unicode編碼字符集中,,字符“A”的編碼是U+0041,,那么0041就是一個代碼點(diǎn)。


代碼單元指的是字符所占空間的單元,。例如在UTF-32中,,一個代碼單元為32位,一個字符占用32位,,恰好使用一個代碼單元,,這種方式會耗費(fèi)大量內(nèi)存。在UTF-16中,,一個代碼單元為16位,,值 U+0000 至 U+FFFF 編碼對應(yīng)一個字符,每個字符占用一個代碼單元,,但是,,對于超過這個范圍的那些增補(bǔ)字符的編碼,需要兩個這樣的單元(即32位),。而在UTF-8中,,一個代碼單元為8位,UTF-8 使用一至四個字節(jié)的序列對編碼 Unicode 代碼點(diǎn)進(jìn)行編碼,,原理同UTF-32和UTF-16,。



3.String字符串常量


在Java語言中,一個String字符串常量對應(yīng)著一個String對象,,并且是不可更改和繼承的(因?yàn)镾tring類被final關(guān)鍵字修飾),。Java語言這樣設(shè)計(jì),主要是為了使得字符串常量(注意是字符串常量,,字符串變量不符合這里所講的規(guī)則)可以共享,,因?yàn)镴VM將字符串常量放入公共的存儲池中,,不同的變量可以引用相同的字符串常量,。

以上代碼運(yùn)行結(jié)果為:true。這就說明a和b引用的是同一String對象,。


4.基本數(shù)據(jù)類型轉(zhuǎn)換規(guī)則


在雙操作數(shù)運(yùn)算中,,會根據(jù)操作數(shù)類型將低級的一個類型轉(zhuǎn)換為高級的一個類型。

1)只要兩個操作數(shù)中有一個是double類型的,,另一個將會被轉(zhuǎn)換成double類型,,并且結(jié)果也是double類型; 

2)只要兩個操作數(shù)中有一個是float類型的,,另一個將會被轉(zhuǎn)換成float類型,,并且結(jié)果也是float類型; 

3)只要兩個操作數(shù)中有一個是long類型的,另一個將會被轉(zhuǎn)換成long類型,,并且結(jié)果也是long類型,; 

4)兩個操作數(shù)(包括byte、short,、int,、char)都將會被轉(zhuǎn)換成int類型,并且結(jié)果也是int類型,。


5.按值調(diào)用與按引用調(diào)用


按值調(diào)用表示方法接收的是調(diào)用者提供的參數(shù)值,。按引用調(diào)用表示方法接收的是調(diào)用者提供的是調(diào)用者提供的參數(shù)地址。Java程序設(shè)計(jì)語言總是按值調(diào)用的,。下面是反例代碼:

以上代碼啟動交換a和b所引用的對象,,但實(shí)際編譯執(zhí)行會發(fā)現(xiàn)沒有成功交換。這也就證明Java不是按引用調(diào)用的,,a和b僅代表兩個Person對象的值,,而不是代表兩個對象的引用,在參數(shù)傳遞上與int等基本類型的值沒有區(qū)別,。



6.對象初始化


在使用構(gòu)造器初始化對象時,,首先運(yùn)行初始化塊,然后運(yùn)行構(gòu)造器的主題部分,。調(diào)用構(gòu)造器的具體初始化步驟如下:

1)類的所有數(shù)據(jù)域被初始化為默認(rèn)值(0,、false或null)。

2)按照在類中聲明的次序,,依次執(zhí)行所有初始化語句和初始化塊,。

3)如果構(gòu)造器第一行調(diào)用了第二個構(gòu)造器,則執(zhí)行第二個構(gòu)造器,。

4)執(zhí)行構(gòu)造器的主體,。

類第一次加載的時候,將會進(jìn)行靜態(tài)域的初始化,。所有的靜態(tài)初始化語句以及靜態(tài)初始化塊都將依照定義的順序進(jìn)行,。

使用super調(diào)用構(gòu)造器的語句必須是子類構(gòu)造器的第一條語句。


7.數(shù)組


在Java中,,子類數(shù)組的引用可以轉(zhuǎn)換成父類數(shù)組的引用,,而不需要采用強(qiáng)制類型轉(zhuǎn)換。


8.繼承


在覆蓋一個方法的時候,,子類方法不能低于父類方法的可見性,。即父類方法是protected的,子類覆蓋的方法只能是protected或public的,。


9.final修飾的類


如果將一個類聲明為final的,,只有其中的方法自動成為final,而不包括域。


10.equals方法


Object類的equals方法用于檢測一個對象與另一個對象是否相等,,即判斷兩個變量的引用是否相同,。如果重新定義了equals方法,就必須重新定義hashCode方法,,因?yàn)橄蛏⒘斜碇刑砑訑?shù)據(jù)時會根據(jù)hashCode和equals方法來確定插入位置,。如果x.equals(y)返回true,那么x.hashCode()與y.hashCode()的返回值必須相同,。

由于枚舉值具有固定的實(shí)例,,因此直接使用“==”就可以判定兩個枚舉值是否相同,而不需使用equals方法,。



11.Class類


JVM會為每個加載的類生成一個Class類型的實(shí)例,,用于跟蹤對象所屬的類,獲取Class類型實(shí)例的方法如下:

1)Object類中的getClass()方法將會返回一個Class類型的實(shí)例,。

2)Class.forName(className)可以返回className指定類的Class實(shí)例,。

3)MyClass.class可以返回MyClass類的Class實(shí)例。


12.局部類


在方法中聲明的類稱為局部類(也屬于內(nèi)部類),,局部類不僅能夠訪問包含它們的外部類,,還可以訪問局部變量。不過,,可以被訪問的局部變量必須被聲明為final,。


13.代理


利用代理可以在運(yùn)行時創(chuàng)建一個實(shí)現(xiàn)了一組給定接口的新類,這種功能只有在編譯時無法確定需要實(shí)現(xiàn)哪個接口時才有必要使用,。我們需要提供一個實(shí)現(xiàn)InvocationHandler接口的類來處理調(diào)用過程:





14.限定泛型變量


關(guān)于類型變量限定的問題,,一直以來是不少程序員感覺困惑的地方,本條就這個問題簡要討論一下,。Java泛型一面有以下兩種類型限定的泛型:

    限定類型可以有多個,,使用“&”分隔。比如:


無論何時定義一個泛型類型,,都自動提供了一個相應(yīng)的原始類型,。程序運(yùn)行時,擦除類型變量,,并替換為第一個限定類型(比如被替換為Comparable),,無限定的變量使用Object,。

SaneseeDemo

不能用類型參數(shù)代替基本類型,。因此沒有SaneseeDemo,只有SaneseeDemo,。

不能實(shí)例化參數(shù)化類型的數(shù)組,,例如:


這是因?yàn)閍rray被擦除類型之后,它的類型為SaneseeDemo [],元素類型為SaneseeDemo,,則相應(yīng)的原始類型為Object[],,那么就可以往里面添加任何類型的元素,也就會出現(xiàn)類型錯誤,。

如果需要使用參數(shù)化類型對象,,只有一種安全而有效的方法:使用ArrayList。

同時,,也不能在靜態(tài)域或方法中引用類型變量,,無法通過編譯,比如:

因?yàn)轭愋筒脸?,就變?yōu)樵碱愋蚈bject了,。如果它可以正常執(zhí)行,那么任何類型的T最終都會變?yōu)镺bject,,那么不管傳入什么類型的T,,最終只能獲取相同的單例,這與我們想要的功能是不一致的,。


不能拋出或捕獲泛型類型的異常,。

Sanesee不是Sanesee的子類,因此不能將Sanesee類型的值賦給Sanesee類型的值,。


不能向類型的變量調(diào)用set方法的,。假設(shè)它可以執(zhí)行,因?yàn)槌绦驘o法知道這個變量的具體類型,,它的類型可能是Manager,,也可能是Executive,那么就會出現(xiàn)類型轉(zhuǎn)換錯誤,。只能向這個變量調(diào)用get方法,,因?yàn)槌绦虬勋@得的值自動轉(zhuǎn)換為Employee類型,子類型可以自動轉(zhuǎn)換為父類型,。


不能向類型的變量調(diào)用get方法,,因?yàn)槌绦驘o法知道返回的具體類型,它的類型可能是Person,,也有可能是Object,。只能調(diào)用set方法,因?yàn)椴还苁莻魅隕mployee還是其子類,,都可以成功執(zhí)行,。


總之,帶有super限定的通配符可以向泛型對象寫入,,帶有extends限定的通配符可以從泛型對象讀取,。而Sanesee和Sanesee類型的不同點(diǎn)在于,,Sanesee類型擦除以后就是Object了,所以根本無法使用Object類型的對象去調(diào)用它,,只有將它放在靜態(tài)方法中執(zhí)行一些簡單的操作,。


15.多線程


當(dāng)對一個線程調(diào)用interupt方法時,線程的中斷狀態(tài)將被置位,。每個線程都具有一個boolean類型的中斷標(biāo)志,,通過它來判斷線程是否被中斷:

Thread.currentThread().isInterupted()


線程的run方法不能拋出任何受檢異常,而受檢異常會導(dǎo)致程序終止,。然而,,不需要使用catch語句來處理可以被傳播的異常。相反,,就在線程死亡之前,,異常被傳遞到一個用于未捕獲異常的處理器??梢允褂胹etUncaughtExceptionHandler為任何線程安裝一個處理器,。


可以調(diào)用ReentrantLock的lock和unlock方法獲取鎖或解除鎖,也可以調(diào)用條件對象Condition(由ReentrantLock的newCondition方法獲?。┑腶wait和singal實(shí)現(xiàn)等待或通知功能,。兩種方式的不同點(diǎn)在于,lock獲取到的鎖,,會等到程序執(zhí)行結(jié)束調(diào)用unlock時才會釋放,,哪怕正在執(zhí)行耗時比較長的任務(wù),或者處于等待狀態(tài),。而Condition在需要等待的地方調(diào)用await方法,,進(jìn)入等待集,當(dāng)鎖可用時,,該線程繼續(xù)保持阻塞狀態(tài),,直到另一個線程調(diào)用同一條件上的singalAll方法為止(singal方法可以隨機(jī)解除一個線程的阻塞狀態(tài))。然而,,最好不使用Lock/Condition或synchronized關(guān)鍵字,,可以使用java.util.concurrent包中的任何一種機(jī)制,它會為你處理所有的加鎖,。如果一定得使用關(guān)鍵字,,優(yōu)先使用synchronized,這樣可以減少代碼的數(shù)量,,其次才是Lock/Condition,。


ThreadLocal類型可以使得每個線程擁有自己的獨(dú)立的變量。volatile類型為實(shí)例域的訪問提供了一種免鎖機(jī)制,,可以使得線程每次都可以訪問到最新的值(volatile變量不能保證原子性),。


ReentrantReadWriteLock類適合讀數(shù)據(jù)多而寫數(shù)據(jù)少的情形:

ReentrantReadWriteLock.readLock();//多個線程共享,,排斥寫

ReentrantReadWriteLock.writeLock();//單個線程使用,,排斥讀寫

官方建議放棄使用stop和suspend方法,,是因?yàn)閟top強(qiáng)制終止一個線程是極不安全的操作,而suspend本身容易導(dǎo)致死鎖,。

在阻塞隊(duì)列中,,生產(chǎn)者向隊(duì)列中插入元素,消費(fèi)者向隊(duì)列獲取元素,。當(dāng)隊(duì)列為空時,,消費(fèi)者線程會被阻塞;當(dāng)隊(duì)列慢時,,生產(chǎn)者線程將被阻塞,。LinkedBlockingQueue可以不限容量,而ArrayBlockingQueue需要指定容量,。PriorityBlockingQueue是一個帶有優(yōu)先級的隊(duì)列,,DelayQueue需要在指定延遲慢之后才能移除元素。LinkedTransferQueue的transfer(item)方法允許生產(chǎn)者線程等待,,直到消費(fèi)者準(zhǔn)備就緒并移除這個item元素,。


java.util.concurrent包提供了Map、集合等的并發(fā)實(shí)現(xiàn),,ConcurrentHashMap,、ConcurrentSkipListMap、ConcurrentSkipListSet和ConcurrentLinkedQueue,,允許并發(fā)訪問數(shù)據(jù)結(jié)構(gòu),。


任何集合類型可以通過使用同步包裝器變成線程安全的(當(dāng)然最好使用java.util.concurrent包中定義的集合,因?yàn)樗鼈兘?jīng)過了精心的設(shè)計(jì)):

List list = Collections.synchronizedList(new ArrayList);

Map map = Collections.synchronizedMap(new HashMap());


Runnable封裝了一個異步運(yùn)行的任務(wù),,可以看做沒有參數(shù)和返回值的異步方法,。Callable與Runnable類似,但它有返回值,。


Executors是一個線程執(zhí)行器,,用于管理線程的創(chuàng)建和執(zhí)行,使用它可以創(chuàng)

建多種線程池,,常見線程池如下:

Executors.newCachedThreadPool:必要時創(chuàng)建新線程,,空閑線程會保留60秒。

Executors.newFixedThreadPool:創(chuàng)建固定容量的線程池,。

Executors.newSingleThreadPool:創(chuàng)建只有一個線程的線程池,。

Executors.newScheduledThreadPool:用于預(yù)定指定的線程池。


原文鏈接:http://www./article/15-forgettable-java-questions




    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多