一、寫(xiě)一個(gè)單例
現(xiàn)在有很經(jīng)典的五種創(chuàng)建方式,這里不再贅述,當(dāng)時(shí)我寫(xiě)的一個(gè)靜態(tài)內(nèi)部類形式。
public static class Singleton{
private Singleton(){};
public static getInstance(){
return Holder.singleton;
}
private static class Holder{
private static final Singleton singleton = new Singleton();
}
}
寫(xiě)完就后悔了,還是應(yīng)該寫(xiě)經(jīng)常用的雙重檢驗(yàn)鎖模式,恩...果然面試官就問(wèn)了這樣寫(xiě)能保證線程安全嗎?答案是肯定的!但是他叫我分析一下,當(dāng)時(shí)就懵逼了。接下來(lái)就開(kāi)始懷疑人生了,沒(méi)有一個(gè)鎖是如何保證線程安全的...感覺(jué)是不是自己寫(xiě)錯(cuò)了,還是不應(yīng)該裝逼,老老實(shí)實(shí)寫(xiě)DCL模式。
其實(shí)當(dāng)時(shí)我是想講靜態(tài)變量是屬于程序本身,第一次加載該類時(shí)才會(huì)為其分配內(nèi)存空間初始化。但當(dāng)時(shí)在腦海中盤(pán)旋的是當(dāng)兩個(gè)線程同時(shí)調(diào)用getInstance()方法時(shí)該怎么辦?當(dāng)時(shí)腦海中反駁自己的理由是創(chuàng)建一個(gè)對(duì)象并非是原子操作...最后給面試官老老實(shí)實(shí)說(shuō)了因?yàn)樽约浩綍r(shí)不常用靜態(tài)內(nèi)部類的緣故。
還是感覺(jué)自己太緊張了,我把它理解為
public static class Singleton{
private static final Singleton singleton;
private Singleton(){};
public static getInstance(){
if(singleton==null)
singleton = new Singleton;
return singleton;
}
}
這里也需要惡補(bǔ)一下實(shí)例變量類變量的初始化時(shí)機(jī),類變量是當(dāng)我們程序第一次加載到內(nèi)存的時(shí)候初始化,并且初始化時(shí)在靜態(tài)代碼塊中(javap命令查看編譯后的字節(jié)碼可以發(fā)現(xiàn)初始化是在靜態(tài)代碼塊中,而實(shí)例變量初始化是在構(gòu)造方法中),所以創(chuàng)建靜態(tài)變量是在第一次加載到內(nèi)容的時(shí)候創(chuàng)建的,并且保證只創(chuàng)建過(guò)一次,無(wú)論哪個(gè)線程調(diào)用的時(shí)候都是調(diào)用的一個(gè)已經(jīng)實(shí)例化的對(duì)象,都是線程安全的。只不過(guò)靜態(tài)內(nèi)部類采用的延時(shí)創(chuàng)建對(duì)象的策略,只有我們調(diào)用getInstance()方法的時(shí)候才把靜態(tài)內(nèi)部類加載到內(nèi)存中,從而實(shí)例化我們的對(duì)象。
二、向容量為100的int型數(shù)組中隨機(jī)插入0~99
當(dāng)時(shí)我的第一反應(yīng)是去隨機(jī)數(shù),插入數(shù)組中,如果檢測(cè)到當(dāng)前下標(biāo)位置發(fā)生碰撞則向前或向后移動(dòng),但是感覺(jué)這樣時(shí)間復(fù)雜度太大了,可能會(huì)達(dá)到n^2,所以能否將數(shù)組類似于希爾排序一樣分為10個(gè)組,又想了一下能否在010中取隨機(jī)數(shù),并且額外增加一個(gè)長(zhǎng)度為10的數(shù)組記錄每組容量的多少。如果當(dāng)前組滿了則向前或向后移動(dòng)。就這樣胡思亂想了十分鐘,最后給面試官說(shuō)了一下思路,面試官建議我下次按照最自己最原始的做法完成,再去想優(yōu)化,就這樣GG了。最后還是得多去看看算法,大公司還是很注意這方面的內(nèi)容。最后一個(gè)朋友提醒了我,應(yīng)該使用類似洗牌的算法~果然是刷了劍指offer和程序之美的老鳥(niǎo)!
void shuffle(int counts[]){
Random random = new Random();
int temp;
for(int i = 0;i < counts.length;i++){
//這樣做保證了每次交換的都大于i,防止與已經(jīng)交換過(guò)的數(shù)再交換一次,保證打亂的順序
int j = i+random.nextInt(counts.length-i);
//i,j進(jìn)行順序交換
temp = counts[i];
counts[i] = counts[j];
counts[j] = temp;
}
}
三、邏輯問(wèn)題:取100個(gè)小球,每次只能去一個(gè)或者兩個(gè),假設(shè)你先取,如何保證你能贏。
這個(gè)問(wèn)題自己有點(diǎn)略傻,當(dāng)時(shí)想的是100個(gè)太多,嘗試一下逆推,最后想出最后剩3個(gè)的時(shí)候自己肯定會(huì)贏的。面試官說(shuō)思路是對(duì)的,讓我回去再想一想,真蠢,每次自己取完后保證是3的倍數(shù)最后肯定會(huì)剩3個(gè)的。
其他的問(wèn)題都是基礎(chǔ)的java面試題,唯一的遺憾就是沒(méi)有問(wèn)到android的面試題。