java寶典
說(shuō)明,為了減輕大家的負(fù)擔(dān)和節(jié)省大家的時(shí)間,一些過(guò)時(shí)知識(shí)點(diǎn)和被筆試概率極低的題目不再被收錄和分析。
回答問(wèn)題的思路:先正面敘述一些基本的核心知識(shí),然后描述一些特殊的東西,最后再來(lái)一些錦上添花的東西。要注意有些不是錦上添花,而是畫(huà)蛇添足的東西,不要隨便寫(xiě)上。把答題像寫(xiě)書(shū)一樣寫(xiě)。我要回答一個(gè)新技術(shù)的問(wèn)題大概思路和步驟是:我們想干什么,干這個(gè)遇到了什么問(wèn)題,現(xiàn)在用什么方式來(lái)解決。其實(shí)我們講課也是這樣一個(gè)思路。
例如,將ajax時(shí),我們希望不改變?cè)瓉?lái)的整個(gè)網(wǎng)頁(yè),而知識(shí)改變網(wǎng)頁(yè)中的局部?jī)?nèi)容,例如,用戶名校驗(yàn),級(jí)聯(lián)下拉列表,下來(lái)樹(shù)狀菜單。用傳統(tǒng)方式,就是瀏覽器自己直接向服務(wù)器發(fā)請(qǐng)求,服務(wù)器返回新頁(yè)面回蓋掉老頁(yè)面,這樣就不流暢了。
對(duì)于這個(gè)系列里的問(wèn)題,每個(gè)學(xué)Java的人都應(yīng)該搞懂。當(dāng)然,如果只是學(xué)Java玩玩就無(wú)所謂了。如果你認(rèn)為自己已經(jīng)超越初學(xué)者了,卻不很懂這些問(wèn)題,請(qǐng)將你自己重歸初學(xué)者行列。
答題時(shí),先答是什么,再答有什么作用和要注意什么(這部分最重要,展現(xiàn)自己的心得)
答案的段落分別,層次分明,條理清楚都非常重要,從這些表面的東西也可以看出一個(gè)人的習(xí)慣、辦事風(fēng)格、條理等。
要將你做出答案的思路過(guò)程,或者說(shuō)你記住答案的思想都寫(xiě)下來(lái)。把答題想著是辯論賽。答題就是給別人講道理、擺事實(shí)。答題不局限于什么格式和形式,就是要將自己的學(xué)識(shí)展現(xiàn)出來(lái)!
別因?yàn)槿思翌}目本來(lái)就模棱兩可,你就心里膽怯和沒(méi)底氣了,不敢回答了。你要大膽地指出對(duì)方題目很模糊和你的觀點(diǎn),不要把面試官想得有多高,其實(shí)他和你就是差不多的,你想想,如果他把你招進(jìn)去了,你們以后就是同事了,可不是差不多的嗎?
關(guān)于就業(yè)薪水,如果你是應(yīng)屆生,那不能要高工資,好比大餅的故事,要拿高工資,就去中關(guān)村!少數(shù)人基礎(chǔ)確實(shí)很好,在校期間確實(shí)又做過(guò)一些項(xiàng)目,那仍然是可以要到相對(duì)高的工資的。基礎(chǔ)好的冷桂華的故事。
初級(jí)程序員薪水:2000-4500
中級(jí)程序員薪水:4000-7000
高級(jí)程序員薪水:7000以上
公司招聘程序員更看重的要用到的編碼技術(shù)、而不是那些業(yè)務(wù)不太相關(guān)的所謂項(xiàng)目經(jīng)歷:
1.公司想招什么樣的人2.公司面試會(huì)問(wèn)什么,.3.簡(jiǎn)歷怎么寫(xiě)4怎樣達(dá)到簡(jiǎn)歷上的標(biāo)準(zhǔn)(培訓(xùn)中心教項(xiàng)目的目的)
對(duì)于一些公司接到了一些項(xiàng)目,想招聘一些初中級(jí)的程序員過(guò)來(lái)幫助寫(xiě)代碼,完成這個(gè)項(xiàng)目,你更看重的是他的專業(yè)技術(shù)功底,還是以前做過(guò)幾個(gè)項(xiàng)目的經(jīng)歷呢?我們先排除掉那些編碼技術(shù)功底好,又正好做過(guò)相似項(xiàng)目的情況,實(shí)際上,這種魚(yú)和熊掌兼得的情況并不常見(jiàn)。其實(shí)公司很清楚,只要招聘進(jìn)來(lái)的人技術(shù)真的很明白,那他什么項(xiàng)目都可以做出來(lái),公司招人不是讓你去重復(fù)做你以前的項(xiàng)目,而是做一個(gè)新項(xiàng)目,業(yè)務(wù)方面,你只要進(jìn)了項(xiàng)目團(tuán)隊(duì),自然就能掌握。所以,大多數(shù)招聘單位在招聘那些編碼級(jí)別的程序員時(shí)也沒(méi)指望能招聘到做過(guò)類似項(xiàng)目的人,也不會(huì)刻意去找做過(guò)類似項(xiàng)目的人,用人單位也不是想把你招進(jìn),然后把你以前做過(guò)的項(xiàng)目重做一遍,所以,用人單位更看重招進(jìn)來(lái)的人對(duì)要用到的編碼技術(shù)的功底到底怎樣,技術(shù)扎實(shí)不扎實(shí),項(xiàng)目則只要跟著開(kāi)發(fā)團(tuán)隊(duì)走,自然就沒(méi)問(wèn)題。除非是一些非常專業(yè)的行業(yè),要招聘特別高級(jí)的開(kāi)發(fā)人員和系統(tǒng)分析師,招聘單位才特別注重他的項(xiàng)目經(jīng)驗(yàn)和行業(yè)經(jīng)驗(yàn),要去找到行業(yè)高手,公司才關(guān)心項(xiàng)目和與你聊項(xiàng)目的細(xì)節(jié),這樣的人通常都不是通過(guò)常規(guī)招聘渠道去招聘進(jìn)來(lái)的,而是通過(guò)各種手段挖過(guò)來(lái)的,這情況不再我今天要討論的范圍中。
技術(shù)學(xué)得明白不明白,人家?guī)讉€(gè)問(wèn)題就把你的深淺問(wèn)出來(lái)了,只要問(wèn)一些具體的技術(shù)點(diǎn),就很容易看出你是真懂還是假懂,很容看出你的技術(shù)深度和實(shí)力,所以,技術(shù)是來(lái)不得半點(diǎn)虛假的,必須扎扎實(shí)實(shí)。
由于項(xiàng)目的種類繁多,涉及到現(xiàn)實(shí)生活中的各行各業(yè),什么五花八門(mén)的業(yè)務(wù)都有,例如,酒店房間預(yù)定管理,公司車(chē)輛調(diào)度管理,學(xué)校課程教室管理,超市進(jìn)銷(xiāo)存管理,知識(shí)內(nèi)容管理,等等……成千上萬(wàn)等等,但是,不管是什么項(xiàng)目,采用的無(wú)非都是我們學(xué)習(xí)的那些目前流行和常用的技術(shù)。技術(shù)好、經(jīng)驗(yàn)豐富,則項(xiàng)目做出來(lái)的效率高些,程序更穩(wěn)定和更容易維護(hù)些;技術(shù)差點(diǎn),碰碰磕磕最后也能把項(xiàng)目做出來(lái),無(wú)非是做的周期長(zhǎng)點(diǎn)、返工的次數(shù)多點(diǎn),程序代碼寫(xiě)得差些,用的技術(shù)笨拙點(diǎn)。如果一個(gè)人不是完完全全做過(guò)某個(gè)項(xiàng)目,他是不太關(guān)心該項(xiàng)目的業(yè)務(wù)的,對(duì)其中的一些具體細(xì)節(jié)更是一竅不知,(如果我招你來(lái)做圖書(shū)管理,你項(xiàng)目經(jīng)歷說(shuō)你做過(guò)汽車(chē)調(diào)度,那我能問(wèn)你汽車(chē)調(diào)度具體怎么回事嗎?不會(huì),所以,你很容易蒙混過(guò)去的)而一個(gè)程序員的整個(gè)職業(yè)生涯中能實(shí)實(shí)在在和完完整整做出來(lái)的項(xiàng)目沒(méi)幾個(gè),更別說(shuō)在多個(gè)不同行業(yè)的項(xiàng)目了,有的程序員更是一輩子都只是在做某一個(gè)行業(yè)的項(xiàng)目,結(jié)果他就成了這個(gè)行業(yè)的專家(專門(mén)干一件事的家伙)。所以,技術(shù)面試官通常沒(méi)正好親身經(jīng)歷過(guò)你簡(jiǎn)歷寫(xiě)的那些項(xiàng)目,他不可能去問(wèn)你寫(xiě)的那些項(xiàng)目的具體細(xì)節(jié),而是只能泛泛地問(wèn)你這個(gè)項(xiàng)目是多少人做的,做了多長(zhǎng)時(shí)間,開(kāi)發(fā)的過(guò)程,你在做項(xiàng)目的過(guò)程中有什么心得和收獲,用的什么技術(shù)等面上的問(wèn)題,所以,簡(jiǎn)歷上的項(xiàng)目經(jīng)歷可以含有很多水分,很容易作假,技術(shù)面試官也無(wú)法在項(xiàng)目上甄別你的真?zhèn)巍?br>
簡(jiǎn)歷該怎么寫(xiě):精通那些技術(shù),有一些什么項(xiàng)目經(jīng)歷
教項(xiàng)目是為了鞏固和靈活整合運(yùn)用技術(shù),增強(qiáng)學(xué)習(xí)的趣味性,熟悉做項(xiàng)目的流程,或得一些專業(yè)課程中無(wú)法獲得的特有項(xiàng)目經(jīng)驗(yàn),增強(qiáng)自己面試的信心。講的項(xiàng)目應(yīng)該真實(shí)可靠才有價(jià)值,否則,表面上是項(xiàng)目,實(shí)際上還是知識(shí)點(diǎn)的整合,對(duì)鞏固技術(shù)點(diǎn)和增強(qiáng)學(xué)習(xí)的趣味性,但無(wú)法獲得實(shí)際的項(xiàng)目經(jīng)驗(yàn)。(項(xiàng)目主要是增加你經(jīng)驗(yàn)的可信度,獲得更多面試機(jī)會(huì),真正能不能找到工作,找到好工作,主要看你鍵盤(pán)上的功夫了)
建議大家盡量開(kāi)自己的blog,堅(jiān)持每天寫(xiě)技術(shù)blog。在簡(jiǎn)歷上寫(xiě)上自己的blog地址,可以多轉(zhuǎn)載一些技術(shù)文章。
Java就業(yè)培訓(xùn)教程就是小沈陽(yáng)
1. Java基礎(chǔ)部分
基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)法,集合的語(yǔ)法,io 的語(yǔ)法,虛擬機(jī)方面的語(yǔ)法,其他
1、一個(gè)".java"源文件中是否可以包括多個(gè)類(不是內(nèi)部類)?有什么限制?
可以有多個(gè)類,但只能有一個(gè)public的類,并且public的類名必須與文件名相一致。
2、&和&&的區(qū)別。
&和&&都可以用作邏輯與的運(yùn)算符,表示邏輯與(and),當(dāng)運(yùn)算符兩邊的表達(dá)式的結(jié)果都為true時(shí),整個(gè)運(yùn)算結(jié)果才為true,否則,只要有一方為false,則結(jié)果為false。
&&還具有短路的功能,即如果第一個(gè)表達(dá)式為false,則不再計(jì)算第二個(gè)表達(dá)式,例如,對(duì)于if(str != null && !str.equals(“”))表達(dá)式,當(dāng)str為null時(shí),后面的表達(dá)式不會(huì)執(zhí)行,所以不會(huì)出現(xiàn)NullPointerException如果將&&改為&,則會(huì)拋出NullPointerException異常。If(x==33 & ++y>0) y會(huì)增長(zhǎng),If(x==33 && ++y>0)不會(huì)增長(zhǎng)
&還可以用作位運(yùn)算符,當(dāng)&操作符兩邊的表達(dá)式不是boolean類型時(shí),&表示按位與操作,我們通常使用0x0f來(lái)與一個(gè)整數(shù)進(jìn)行&運(yùn)算,來(lái)獲取該整數(shù)的最低4個(gè)bit位,例如,0x31 & 0x0f的結(jié)果為0x01。
備注:這道題先說(shuō)兩者的共同點(diǎn),再說(shuō)出&&和&的特殊之處,并列舉一些經(jīng)典的例子來(lái)表明自己理解透徹深入、實(shí)際經(jīng)驗(yàn)豐富。
3、Java有沒(méi)有g(shù)oto?
java中的保留字,現(xiàn)在沒(méi)有在java中使用。
4、在JAVA中,如何跳出當(dāng)前的多重嵌套循環(huán)?
在Java中,要想跳出多重循環(huán),可以在外面的循環(huán)語(yǔ)句前定義一個(gè)標(biāo)號(hào),然后在里層循環(huán)體的代碼中使用帶有標(biāo)號(hào)的break 語(yǔ)句,即可跳出外層循環(huán)。例如,
ok:
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
System.out.println(“i=” + i + “,j=” + j);
if(j == 5) break ok;
}
}
另外,我個(gè)人通常并不使用標(biāo)號(hào)這種方式,而是讓外層的循環(huán)條件表達(dá)式的結(jié)果可以受到里層循環(huán)體代碼的控制,例如,要在二維數(shù)組中查找到某個(gè)數(shù)字。
boolean found = false;
for(int i=0;i<10 && !found;i++)
{
for(int j=0;j<10;j++)
{
System.out.println(“i=” + i + “,j=” + j);
if(j == 5)
{
found = true;
break;
}
}
}
5、switch是否能作用在byte上,是否能作用在long上,是否能作用在String上?
在switch(expr1)中,expr1只能是一個(gè)整數(shù)表達(dá)式或者枚舉常量(更大字體),整數(shù)表達(dá)式可以是int基本類型或Integer包裝類型,由于,byte,short,char都可以隱含轉(zhuǎn)換為int,所以,這些類型以及這些類型的包裝類型也是可以的。顯然,long和String類型都不符合sitch的語(yǔ)法規(guī)定,并且不能被隱式轉(zhuǎn)換成int類型,所以,它們不能作用于swtich語(yǔ)句中。
6、short s1 = 1; s1 = s1 + 1;有什么錯(cuò)? short s1 = 1; s1 += 1;有什么錯(cuò)?
對(duì)于short s1 = 1; s1 = s1 + 1; 由于s1+1運(yùn)算時(shí)會(huì)自動(dòng)提升表達(dá)式的類型,所以結(jié)果是int型,再賦值給short類型s1時(shí),編譯器將報(bào)告需要強(qiáng)制轉(zhuǎn)換類型的錯(cuò)誤。
對(duì)于short s1 = 1; s1 += 1;由于 += 是java語(yǔ)言規(guī)定的運(yùn)算符,java編譯器會(huì)對(duì)它進(jìn)行特殊處理,因此可以正確編譯。
7、char型變量中能不能存貯一個(gè)中文漢字?為什么?
char型變量是用來(lái)存儲(chǔ)Unicode編碼的字符的,unicode編碼字符集中包含了漢字,所以,char型變量中當(dāng)然可以存儲(chǔ)漢字啦。不過(guò),如果某個(gè)特殊的漢字沒(méi)有被包含在unicode編碼字符集中,那么,這個(gè)char型變量中就不能存儲(chǔ)這個(gè)特殊漢字。補(bǔ)充說(shuō)明:unicode編碼占用兩個(gè)字節(jié),所以,char類型的變量也是占用兩個(gè)字節(jié)。
備注:后面一部分回答雖然不是在正面回答題目,但是,為了展現(xiàn)自己的學(xué)識(shí)和表現(xiàn)自己對(duì)問(wèn)題理解的透徹深入,可以回答一些相關(guān)的知識(shí),做到知無(wú)不言,言無(wú)不盡。
8、編程題: 用最有效率的方法算出2乘以8等於幾?
2 << 3,
因?yàn)閷⒁粋€(gè)數(shù)左移n位,就相當(dāng)于乘以了2的n次方,那么,一個(gè)數(shù)乘以8只要將其左移3位即可,而位運(yùn)算cpu直接支持的,效率最高,所以,2乘以8等於幾的最效率的方法是2 << 3。
9、請(qǐng)?jiān)O(shè)計(jì)一個(gè)一百億的計(jì)算器
首先要明白這道題目的考查點(diǎn)是什么,一是大家首先要對(duì)計(jì)算機(jī)原理的底層細(xì)節(jié)要清楚、要知道加減法的位運(yùn)算原理和知道計(jì)算機(jī)中的算術(shù)運(yùn)算會(huì)發(fā)生越界的情況,二是要具備一定的面向?qū)ο蟮脑O(shè)計(jì)思想。
首先,計(jì)算機(jī)中用固定數(shù)量的幾個(gè)字節(jié)來(lái)存儲(chǔ)的數(shù)值,所以計(jì)算機(jī)中能夠表示的數(shù)值是有一定的范圍的,為了便于講解和理解,我們先以byte 類型的整數(shù)為例,它用1個(gè)字節(jié)進(jìn)行存儲(chǔ),表示的最大數(shù)值范圍為-128到+127。-1在內(nèi)存中對(duì)應(yīng)的二進(jìn)制數(shù)據(jù)為11111111,如果兩個(gè)-1相加,不考慮Java運(yùn)算時(shí)的類型提升,運(yùn)算后會(huì)產(chǎn)生進(jìn)位,二進(jìn)制結(jié)果為1,11111110,由于進(jìn)位后超過(guò)了byte類型的存儲(chǔ)空間,所以進(jìn)位部分被舍棄,即最終的結(jié)果為11111110,也就是-2,這正好利用溢位的方式實(shí)現(xiàn)了負(fù)數(shù)的運(yùn)算。-128在內(nèi)存中對(duì)應(yīng)的二進(jìn)制數(shù)據(jù)為10000000,如果兩個(gè)-128相加,不考慮Java運(yùn)算時(shí)的類型提升,運(yùn)算后會(huì)產(chǎn)生進(jìn)位,二進(jìn)制結(jié)果為1,00000000,由于進(jìn)位后超過(guò)了byte類型的存儲(chǔ)空間,所以進(jìn)位部分被舍棄,即最終的結(jié)果為00000000,也就是0,這樣的結(jié)果顯然不是我們期望的,這說(shuō)明計(jì)算機(jī)中的算術(shù)運(yùn)算是會(huì)發(fā)生越界情況的,兩個(gè)數(shù)值的運(yùn)算結(jié)果不能超過(guò)計(jì)算機(jī)中的該類型的數(shù)值范圍。由于Java中涉及表達(dá)式運(yùn)算時(shí)的類型自動(dòng)提升,我們無(wú)法用byte類型來(lái)做演示這種問(wèn)題和現(xiàn)象的實(shí)驗(yàn),大家可以用下面一個(gè)使用整數(shù)做實(shí)驗(yàn)的例子程序體驗(yàn)一下:
int a = Integer.MAX_VALUE;
int b = Integer.MAX_VALUE;
int sum = a + b;
System.out.println(“a=”+a+”,b=”+b+”,sum=”+sum);
先不考慮long類型,由于int的正數(shù)范圍為2的31次方,表示的最大數(shù)值約等于2*1000*1000*1000,也就是20億的大小,所以,要實(shí)現(xiàn)一個(gè)一百億的計(jì)算器,我們得自己設(shè)計(jì)一個(gè)類可以用于表示很大的整數(shù),并且提供了與另外一個(gè)整數(shù)進(jìn)行加減乘除的功能,大概功能如下:
()這個(gè)類內(nèi)部有兩個(gè)成員變量,一個(gè)表示符號(hào),另一個(gè)用字節(jié)數(shù)組表示數(shù)值的二進(jìn)制數(shù)
()有一個(gè)構(gòu)造方法,把一個(gè)包含有多位數(shù)值的字符串轉(zhuǎn)換到內(nèi)部的符號(hào)和字節(jié)數(shù)組中
()提供加減乘除的功能
public class BigInteger
{
int sign;
byte[] val;
public Biginteger(String val)
{
sign = ;
val = ;
}
public BigInteger add(BigInteger other)
{
}
public BigInteger subtract(BigInteger other)
{
}
public BigInteger multiply(BigInteger other)
{
}
public BigInteger divide(BigInteger other)
{
}
}
備注:要想寫(xiě)出這個(gè)類的完整代碼,是非常復(fù)雜的,如果有興趣的話,可以參看jdk中自帶的java.math.BigInteger類的源碼。面試的人也知道誰(shuí)都不可能在短時(shí)間內(nèi)寫(xiě)出這個(gè)類的完整代碼的,他要的是你是否有這方面的概念和意識(shí),他最重要的還是考查你的能力,所以,你不要因?yàn)樽约簾o(wú)法寫(xiě)出完整的最終結(jié)果就放棄答這道題,你要做的就是你比別人寫(xiě)得多,證明你比別人強(qiáng),你有這方面的思想意識(shí)就可以了,畢竟別人可能連題目的意思都看不懂,什么都沒(méi)寫(xiě),你要敢于答這道題,即使只答了一部分,那也與那些什么都不懂的人區(qū)別出來(lái),拉開(kāi)了距離,算是矮子中的高個(gè),機(jī)會(huì)當(dāng)然就屬于你了。另外,答案中的框架代碼也很重要,體現(xiàn)了一些面向?qū)ο笤O(shè)計(jì)的功底,特別是其中的方法命名很專業(yè),用的英文單詞很精準(zhǔn),這也是能力、經(jīng)驗(yàn)、專業(yè)性、英語(yǔ)水平等多個(gè)方面的體現(xiàn),會(huì)給人留下很好的印象,在編程能力和其他方面條件差不多的情況下,英語(yǔ)好除了可以使你獲得更多機(jī)會(huì)外,薪水可以高出一千元。
10、使用final關(guān)鍵字修飾一個(gè)變量時(shí),是引用不能變,還是引用的對(duì)象不能變?
使用final關(guān)鍵字修飾一個(gè)變量時(shí),是指引用變量不能變,引用變量所指向的對(duì)象中的內(nèi)容還是可以改變的。例如,對(duì)于如下語(yǔ)句:
final StringBuffer a=new StringBuffer("immutable");
執(zhí)行如下語(yǔ)句將報(bào)告編譯期錯(cuò)誤:
a=new StringBuffer("");
但是,執(zhí)行如下語(yǔ)句則可以通過(guò)編譯:
a.append(" broken!");
有人在定義方法的參數(shù)時(shí),可能想采用如下形式來(lái)阻止方法內(nèi)部修改傳進(jìn)來(lái)的參數(shù)對(duì)象:
public void method(final StringBuffer param)
{
}
實(shí)際上,這是辦不到的,在該方法內(nèi)部仍然可以增加如下代碼來(lái)修改參數(shù)對(duì)象:
param.append("a");
11、"=="和equals方法究竟有什么區(qū)別?
(單獨(dú)把一個(gè)東西說(shuō)清楚,然后再說(shuō)清楚另一個(gè),這樣,它們的區(qū)別自然就出來(lái)了,混在一起說(shuō),則很難說(shuō)清楚)
==操作符專門(mén)用來(lái)比較兩個(gè)變量的值是否相等,也就是用于比較變量所對(duì)應(yīng)的內(nèi)存中所存儲(chǔ)的數(shù)值是否相同,要比較兩個(gè)基本類型的數(shù)據(jù)或兩個(gè)引用變量是否相等,只能用==操作符。
如果一個(gè)變量指向的數(shù)據(jù)是對(duì)象類型的,那么,這時(shí)候涉及了兩塊內(nèi)存,對(duì)象本身占用一塊內(nèi)存(堆內(nèi)存),變量也占用一塊內(nèi)存,例如Objet obj = new Object();變量obj是一個(gè)內(nèi)存,new Object()是另一個(gè)內(nèi)存,此時(shí),變量obj所對(duì)應(yīng)的內(nèi)存中存儲(chǔ)的數(shù)值就是對(duì)象占用的那塊內(nèi)存的首地址。對(duì)于指向?qū)ο箢愋偷淖兞?,如果要比較兩個(gè)變量是否指向同一個(gè)對(duì)象,即要看這兩個(gè)變量所對(duì)應(yīng)的內(nèi)存中的數(shù)值是否相等,這時(shí)候就需要用==操作符進(jìn)行比較。
equals方法是用于比較兩個(gè)獨(dú)立對(duì)象的內(nèi)容是否相同,就好比去比較兩個(gè)人的長(zhǎng)相是否相同,它比較的兩個(gè)對(duì)象是獨(dú)立的。例如,對(duì)于下面的代碼:
String a=new String("foo");
String b=new String("foo");
兩條new語(yǔ)句創(chuàng)建了兩個(gè)對(duì)象,然后用a,b這兩個(gè)變量分別指向了其中一個(gè)對(duì)象,這是兩個(gè)不同的對(duì)象,它們的首地址是不同的,即a和b中存儲(chǔ)的數(shù)值是不相同的,所以,表達(dá)式a==b將返回false,而這兩個(gè)對(duì)象中的內(nèi)容是相同的,所以,表達(dá)式a.equals(b)將返回true。
在實(shí)際開(kāi)發(fā)中,我們經(jīng)常要比較傳遞進(jìn)來(lái)的字符串內(nèi)容是否等,例如,String input = …;input.equals(“quit”),許多人稍不注意就使用==進(jìn)行比較了,這是錯(cuò)誤的,隨便從網(wǎng)上找?guī)讉€(gè)項(xiàng)目實(shí)戰(zhàn)的教學(xué)視頻看看,里面就有大量這樣的錯(cuò)誤。記住,字符串的比較基本上都是使用equals方法。
如果一個(gè)類沒(méi)有自己定義equals方法,那么它將繼承Object類的equals方法,Object類的equals方法的實(shí)現(xiàn)代碼如下:
boolean equals(Object o){
return this==o;
}
這說(shuō)明,如果一個(gè)類沒(méi)有自己定義equals方法,它默認(rèn)的equals方法(從Object 類繼承的)就是使用==操作符,也是在比較兩個(gè)變量指向的對(duì)象是否是同一對(duì)象,這時(shí)候使用equals和使用==會(huì)得到同樣的結(jié)果,如果比較的是兩個(gè)獨(dú)立的對(duì)象則總返回false。如果你編寫(xiě)的類希望能夠比較該類創(chuàng)建的兩個(gè)實(shí)例對(duì)象的內(nèi)容是否相同,那么你必須覆蓋equals方法,由你自己寫(xiě)代碼來(lái)決定在什么情況即可認(rèn)為兩個(gè)對(duì)象的內(nèi)容是相同的。
12、靜態(tài)變量和實(shí)例變量的區(qū)別?
在語(yǔ)法定義上的區(qū)別:靜態(tài)變量前要加static關(guān)鍵字,而實(shí)例變量前則不加。
在程序運(yùn)行時(shí)的區(qū)別:實(shí)例變量屬于某個(gè)對(duì)象的屬性,必須創(chuàng)建了實(shí)例對(duì)象,其中的實(shí)例變量才會(huì)被分配空間,才能使用這個(gè)實(shí)例變量。靜態(tài)變量不屬于某個(gè)實(shí)例對(duì)象,而是屬于類,所以也稱為類變量,只要程序加載了類的字節(jié)碼,不用創(chuàng)建任何實(shí)例對(duì)象,靜態(tài)變量就會(huì)被分配空間,靜態(tài)變量就可以被使用了??傊?,實(shí)例變量必須創(chuàng)建對(duì)象后才可以通過(guò)這個(gè)對(duì)象來(lái)使用,靜態(tài)變量則可以直接使用類名來(lái)引用。
例如,對(duì)于下面的程序,無(wú)論創(chuàng)建多少個(gè)實(shí)例對(duì)象,永遠(yuǎn)都只分配了一個(gè)staticVar變量,并且每創(chuàng)建一個(gè)實(shí)例對(duì)象,這個(gè)staticVar就會(huì)加1;但是,每創(chuàng)建一個(gè)實(shí)例對(duì)象,就會(huì)分配一個(gè)instanceVar,即可能分配多個(gè)instanceVar,并且每個(gè)instanceVar的值都只自加了1次。
public class VariantTest
{
public static int staticVar = 0;
public int instanceVar = 0;
public VariantTest()
{
staticVar++;
instanceVar++;
System.out.println(“staticVar=” + staticVar + ”,instanceVar=” + instanceVar);
}
}
備注:這個(gè)解答除了說(shuō)清楚兩者的區(qū)別外,最后還用一個(gè)具體的應(yīng)用例子來(lái)說(shuō)明兩者的差異,體現(xiàn)了自己有很好的解說(shuō)問(wèn)題和設(shè)計(jì)案例的能力,思維敏捷,超過(guò)一般程序員,有寫(xiě)作能力!
13、是否可以從一個(gè)static方法內(nèi)部發(fā)出對(duì)非static方法的調(diào)用?
不可以。因?yàn)榉莝tatic方法是要與對(duì)象關(guān)聯(lián)在一起的,必須創(chuàng)建一個(gè)對(duì)象后,才可以在該對(duì)象上進(jìn)行方法調(diào)用,而static方法調(diào)用時(shí)不需要?jiǎng)?chuàng)建對(duì)象,可以直接調(diào)用。也就是說(shuō),當(dāng)一個(gè)static方法被調(diào)用時(shí),可能還沒(méi)有創(chuàng)建任何實(shí)例對(duì)象,如果從一個(gè)static方法中發(fā)出對(duì)非static方法的調(diào)用,那個(gè)非static方法是關(guān)聯(lián)到哪個(gè)對(duì)象上的呢?這個(gè)邏輯無(wú)法成立,所以,一個(gè)static方法內(nèi)部發(fā)出對(duì)非static方法的調(diào)用。
14、Integer與int的區(qū)別
int是java提供的8種原始數(shù)據(jù)類型之一。Java為每個(gè)原始類型提供了封裝類,Integer是java為int提供的封裝類。int的默認(rèn)值為0,而Integer的默認(rèn)值為null,即Integer可以區(qū)分出未賦值和值為0的區(qū)別,int則無(wú)法表達(dá)出未賦值的情況,例如,要想表達(dá)出沒(méi)有參加考試和考試成績(jī)?yōu)?的區(qū)別,則只能使用Integer。在JSP開(kāi)發(fā)中,Integer的默認(rèn)為null,所以用el表達(dá)式在文本框中顯示時(shí),值為空白字符串,而int默認(rèn)的默認(rèn)值為0,所以用el表達(dá)式在文本框中顯示時(shí),結(jié)果為0,所以,int不適合作為web層的表單數(shù)據(jù)的類型。
Integer提供了多個(gè)與整數(shù)相關(guān)的操作方法,例如,將一個(gè)字符串轉(zhuǎn)換成整數(shù),Integer中還定義了表示整數(shù)的最大值和最小值的常量。
15、Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math類中提供了三個(gè)與取整有關(guān)的方法:ceil、floor、round,這些方法的作用與它們的英文名稱的含義相對(duì)應(yīng),例如,ceil的英文意義是天花板,該方法就表示向上取整,Math.ceil(11.3)的結(jié)果為12,Math.ceil(-11.3)的結(jié)果是-11;floor的英文意義是地板,該方法就表示向下取整,Math.ceil(11.6)的結(jié)果為11,Math.ceil(-11.6)的結(jié)果是-12;最難掌握的是round方法,它表示“四舍五入”,算法為Math.floor(x+0.5),即將原來(lái)的數(shù)字加上0.5后再向下取整,所以,Math.round(11.5)的結(jié)果為12,Math.round(-11.5)的結(jié)果為-11。
16、作用域public,private,protected,以及不寫(xiě)時(shí)的區(qū)別
這四個(gè)作用域的可見(jiàn)范圍如下表所示。
說(shuō)明:如果在修飾的元素上面沒(méi)有寫(xiě)任何訪問(wèn)修飾符,則表示friendly。
作用域 當(dāng)前類 同一package 子孫類 其他package
public √ √ √ √
protected √ √ √ ×
friendly √ √ × ×
private √ × × ×
備注:只要記住了有4種訪問(wèn)權(quán)限,4個(gè)訪問(wèn)范圍,然后將全選和范圍在水平和垂直方向上分別按排從小到大或從大到小的順序排列,就很容易畫(huà)出上面的圖了。
17、Overload和Override的區(qū)別。Overloaded的方法是否可以改變返回值的類型?
Overload是重載的意思,Override是覆蓋的意思,也就是重寫(xiě)。
重載Overload表示同一個(gè)類中可以有多個(gè)名稱相同的方法,但這些方法的參數(shù)列表各不相同(即參數(shù)個(gè)數(shù)或類型不同)。
重寫(xiě)Override表示子類中的方法可以與父類中的某個(gè)方法的名稱和參數(shù)完全相同,通過(guò)子類創(chuàng)建的實(shí)例對(duì)象調(diào)用這個(gè)方法時(shí),將調(diào)用子類中的定義方法,這相當(dāng)于把父類中定義的那個(gè)完全相同的方法給覆蓋了,這也是面向?qū)ο缶幊痰亩鄳B(tài)性的一種表現(xiàn)。子類覆蓋父類的方法時(shí),只能比父類拋出更少的異常,或者是拋出父類拋出的異常的子異常,因?yàn)樽宇惪梢越鉀Q父類的一些問(wèn)題,不能比父類有更多的問(wèn)題。子類方法的訪問(wèn)權(quán)限只能比父類的更大,不能更小。
至于Overloaded的方法是否可以改變返回值的類型這個(gè)問(wèn)題,要看你倒底想問(wèn)什么呢?這個(gè)題目很模糊。如果幾個(gè)Overloaded的方法的參數(shù)列表不一樣,它們的返回者類型當(dāng)然也可以不一樣。但我估計(jì)你想問(wèn)的問(wèn)題是:如果兩個(gè)方法的參數(shù)列表完全一樣,是否可以讓它們的返回值不同來(lái)實(shí)現(xiàn)重載Override。這是不行的,我們可以用反證法來(lái)說(shuō)明這個(gè)問(wèn)題,因?yàn)槲覀冇袝r(shí)候調(diào)用一個(gè)方法時(shí)也可以不定義返回結(jié)果變量,即不要關(guān)心其返回結(jié)果,例如,我們調(diào)用map.remove(key)方法時(shí),雖然remove方法有返回值,但是我們通常都不會(huì)定義接收返回結(jié)果的變量,這時(shí)候假設(shè)該類中有兩個(gè)名稱和參數(shù)列表完全相同的方法,僅僅是返回類型不同,java就無(wú)法確定編程者倒底是想調(diào)用哪個(gè)方法了,因?yàn)樗鼰o(wú)法通過(guò)返回結(jié)果類型來(lái)判斷。
18、構(gòu)造器Constructor是否可被override?
構(gòu)造器Constructor不能被繼承,因此不能重寫(xiě)Override,但可以被重載Overload。
19、接口是否可繼承接口? 抽象類是否可實(shí)現(xiàn)(implements)接口? 抽象類是否可繼承具體類(concrete class)? 抽象類中是否可以有靜態(tài)的main方法?
接口可以繼承接口。抽象類可以實(shí)現(xiàn)(implements)接口,抽象類是否可繼承實(shí)體類,但前提是實(shí)體類必須有明確的構(gòu)造函數(shù)。抽象類中可以有靜態(tài)的main方法。
備注:只要明白了接口和抽象類的本質(zhì)和作用,這些問(wèn)題都很好回答,你想想,如果你是java語(yǔ)言的設(shè)計(jì)者,你是否會(huì)提供這樣的支持,如果不提供的話,有什么理由嗎?如果你沒(méi)有道理不提供,那答案就是肯定的了。
20、寫(xiě)clone()方法時(shí),通常都有一行代碼,是什么?
clone 有缺省行為,super.clone();因?yàn)槭紫纫迅割愔械某蓡T復(fù)制到位,然后才是復(fù)制自己的成員。
21、面向?qū)ο蟮奶卣饔心男┓矫?br>
計(jì)算機(jī)軟件系統(tǒng)是現(xiàn)實(shí)生活中的業(yè)務(wù)在計(jì)算機(jī)中的映射,而現(xiàn)實(shí)生活中的業(yè)務(wù)其實(shí)就是一個(gè)個(gè)對(duì)象協(xié)作的過(guò)程。面向?qū)ο缶幊叹褪前船F(xiàn)實(shí)業(yè)務(wù)一樣的方式將程序代碼按一個(gè)個(gè)對(duì)象進(jìn)行組織和編寫(xiě),讓計(jì)算機(jī)系統(tǒng)能夠識(shí)別和理解用對(duì)象方式組織和編寫(xiě)的程序代碼,這樣就可以把現(xiàn)實(shí)生活中的業(yè)務(wù)對(duì)象映射到計(jì)算機(jī)系統(tǒng)中。
面向?qū)ο蟮木幊陶Z(yǔ)言有封裝、繼承 、抽象、多態(tài)等4個(gè)主要的特征。
1封裝:
封裝是保證軟件部件具有優(yōu)良的模塊性的基礎(chǔ),封裝的目標(biāo)就是要實(shí)現(xiàn)軟件部件的“高內(nèi)聚、低耦合”,防止程序相互依賴性而帶來(lái)的變動(dòng)影響。在面向?qū)ο蟮木幊陶Z(yǔ)言中,對(duì)象是封裝的最基本單位,面向?qū)ο蟮姆庋b比傳統(tǒng)語(yǔ)言的封裝更為清晰、更為有力。面向?qū)ο蟮姆庋b就是把描述一個(gè)對(duì)象的屬性和行為的代碼封裝在一個(gè)“模塊”中,也就是一個(gè)類中,屬性用變量定義,行為用方法進(jìn)行定義,方法可以直接訪問(wèn)同一個(gè)對(duì)象中的屬性。通常情況下,只要記住讓變量和訪問(wèn)這個(gè)變量的方法放在一起,將一個(gè)類中的成員變量全部定義成私有的,只有這個(gè)類自己的方法才可以訪問(wèn)到這些成員變量,這就基本上實(shí)現(xiàn)對(duì)象的封裝,就很容易找出要分配到這個(gè)類上的方法了,就基本上算是會(huì)面向?qū)ο蟮木幊塘恕?br>
例如,人要在黑板上畫(huà)圓,這一共涉及三個(gè)對(duì)象:人、黑板、圓,畫(huà)圓的方法要分配給哪個(gè)對(duì)象呢?由于畫(huà)圓需要使用到圓心和半徑,圓心和半徑顯然是圓的屬性,如果將它們?cè)陬愔卸x成了私有的成員變量,那么,畫(huà)圓的方法必須分配給圓,它才能訪問(wèn)到圓心和半徑這兩個(gè)屬性,人以后只是調(diào)用圓的畫(huà)圓方法、表示給圓發(fā)給消息而已,畫(huà)圓這個(gè)方法不應(yīng)該分配在人這個(gè)對(duì)象上,這就是面向?qū)ο蟮姆庋b性,即將對(duì)象封裝成一個(gè)高度自治和相對(duì)封閉的個(gè)體,對(duì)象狀態(tài)(屬性)由這個(gè)對(duì)象自己的行為(方法)來(lái)讀取和改變。一個(gè)更便于理解的例子就是,司機(jī)將火車(chē)剎住了,剎車(chē)的動(dòng)作是分配給司機(jī),還是分配給火車(chē),顯然,應(yīng)該分配給火車(chē),因?yàn)樗緳C(jī)自身是不可能有那么大的力氣將一個(gè)火車(chē)給停下來(lái)的,只有火車(chē)自己才能完成這一動(dòng)作,火車(chē)需要調(diào)用內(nèi)部的離合器和剎車(chē)片等多個(gè)器件協(xié)作才能完成剎車(chē)這個(gè)動(dòng)作,司機(jī)剎車(chē)的過(guò)程只是給火車(chē)發(fā)了一個(gè)消息,通知火車(chē)要執(zhí)行剎車(chē)動(dòng)作而已。
抽象:
抽象就是找出一些事物的相似和共性之處,然后將這些事物歸為一個(gè)類,這個(gè)類只考慮這些事物的相似和共性之處,并且會(huì)忽略與當(dāng)前主題和目標(biāo)無(wú)關(guān)的那些方面,將注意力集中在與當(dāng)前目標(biāo)有關(guān)的方面。抽象包括行為抽象和狀態(tài)抽象兩個(gè)方面。例如,定義一個(gè)Person類,如下:
class Person
{
String name;
int age;
}
人本來(lái)是很復(fù)雜的事物,有很多方面,但因?yàn)楫?dāng)前系統(tǒng)只需要了解人的姓名和年齡,所以上面定義的類中只包含姓名和年齡這兩個(gè)屬性,這就是一種抽像,使用抽象可以避免考慮一些與目標(biāo)無(wú)關(guān)的細(xì)節(jié)。我對(duì)抽象的理解就是不要用顯微鏡去看一個(gè)事物的所有方面,這樣涉及的內(nèi)容就太多了,而是要善于劃分問(wèn)題的邊界,當(dāng)前系統(tǒng)需要什么,就只考慮什么。
繼承:
在定義和實(shí)現(xiàn)一個(gè)類的時(shí)候,可以在一個(gè)已經(jīng)存在的類的基礎(chǔ)之上來(lái)進(jìn)行,把這個(gè)已經(jīng)存在的類所定義的內(nèi)容作為自己的內(nèi)容,并可以加入若干新的內(nèi)容,或修改原來(lái)的方法使之更適合特殊的需要,這就是繼承。繼承是子類自動(dòng)共享父類數(shù)據(jù)和方法的機(jī)制,這是類之間的一種關(guān)系,提高了軟件的可重用性和可擴(kuò)展性。
多態(tài):
多態(tài)是指程序中定義的引用變量所指向的具體類型和通過(guò)該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定,而是在程序運(yùn)行期間才確定,即一個(gè)引用變量倒底會(huì)指向哪個(gè)類的實(shí)例對(duì)象,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類中實(shí)現(xiàn)的方法,必須在由程序運(yùn)行期間才能決定。因?yàn)樵诔绦蜻\(yùn)行時(shí)才確定具體的類,這樣,不用修改源程序代碼,就可以讓引用變量綁定到各種不同的類實(shí)現(xiàn)上,從而導(dǎo)致該引用調(diào)用的具體方法隨之改變,即不修改程序代碼就可以改變程序運(yùn)行時(shí)所綁定的具體代碼,讓程序可以選擇多個(gè)運(yùn)行狀態(tài),這就是多態(tài)性。多態(tài)性增強(qiáng)了軟件的靈活性和擴(kuò)展性。例如,下面代碼中的UserDao是一個(gè)接口,它定義引用變量userDao指向的實(shí)例對(duì)象由daofactory.getDao()在執(zhí)行的時(shí)候返回,有時(shí)候指向的是UserJdbcDao這個(gè)實(shí)現(xiàn),有時(shí)候指向的是UserHibernateDao這個(gè)實(shí)現(xiàn),這樣,不用修改源代碼,就可以改變userDao指向的具體類實(shí)現(xiàn),從而導(dǎo)致userDao.insertUser()方法調(diào)用的具體代碼也隨之改變,即有時(shí)候調(diào)用的是UserJdbcDao的insertUser方法,有時(shí)候調(diào)用的是UserHibernateDao的insertUser方法:
UserDao userDao = daofactory.getDao();
userDao.insertUser(user);
比喻:人吃飯,你看到的是左手,還是右手?
22、java中實(shí)現(xiàn)多態(tài)的機(jī)制是什么?
靠的是父類或接口定義的引用變量可以指向子類或具體實(shí)現(xiàn)類的實(shí)例對(duì)象,而程序調(diào)用的方法就是引用所指向的具體實(shí)例對(duì)象的方法,也就是內(nèi)存里正在運(yùn)行的那個(gè)對(duì)象的方法,而不是引用變量的類型中定義的方法。
23、abstract class和interface有什么區(qū)別?
含有abstract修飾符的class即為抽象類,abstract 類不能創(chuàng)建的實(shí)例對(duì)象。含有abstract方法的類必須定義為abstract class,abstract class類中的方法不必是抽象的。abstract class類中定義抽象方法必須在具體子類中實(shí)現(xiàn),所以,不能有抽象構(gòu)造方法或抽象靜態(tài)方法。如果的子類沒(méi)有實(shí)現(xiàn)抽象父類中的所有抽象方法,那么子類也必須定義為abstract類型。
接口(interface)可以說(shuō)成是抽象類的一種特例,接口中的所有方法都必須是抽象的。接口 中的方法定義默認(rèn)為public abstract類型,接口中的成員變量類型默認(rèn)為public static final。
下面比較一下兩者的語(yǔ)法區(qū)別:
1.抽象類可以有構(gòu)造方法,接口中不能有構(gòu)造方法。
2.抽象類中可以有普通成員變量,接口中沒(méi)有普通成員變量
3.抽象類中可以包含非抽象的普通方法,接口中的所有方法必須都是抽象的,不能有非抽象的普通方法。
4. 抽象類中的抽象方法的訪問(wèn)類型可以是public,protected和默認(rèn)類型,但接口中的抽象方法只能是public類型的,并且默認(rèn)即為public abstract類型。
5. 抽象類中可以包含靜態(tài)方法,接口中不能包含靜態(tài)方法
6. 抽象類和接口中都可以包含靜態(tài)成員變量,抽象類中的靜態(tài)成員變量的訪問(wèn)類型可以任意,但接口中定義的變量只能是public static類型,并且默認(rèn)即為public static類型。
7. 一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,但只能繼承一個(gè)抽象類。
下面接著再說(shuō)說(shuō)兩者在應(yīng)用上的區(qū)別:
接口更多的是在系統(tǒng)架構(gòu)設(shè)計(jì)方法發(fā)揮作用,主要用于定義模塊之間的通信契約。而抽象類在代碼實(shí)現(xiàn)方面發(fā)揮作用,可以實(shí)現(xiàn)代碼的重用,例如,模板方法設(shè)計(jì)模式是抽象類的一個(gè)典型應(yīng)用,假設(shè)某個(gè)項(xiàng)目的所有Servlet類都要用相同的方式進(jìn)行權(quán)限判斷、記錄訪問(wèn)日志和處理異常,那么就可以定義一個(gè)抽象的基類,讓所有的Servlet都繼承這個(gè)抽象基類,在抽象基類的service方法中完成權(quán)限判斷、記錄訪問(wèn)日志和處理異常的代碼,在各個(gè)子類中只是完成各自的業(yè)務(wù)邏輯代碼,偽代碼如下:
public abstract class BaseServlet extends HttpServlet
{
public void service(HttpServletRequest request, HttpServletResponse response) throws IOExcetion,ServletException
{
記錄訪問(wèn)日志
進(jìn)行權(quán)限判斷
if(具有權(quán)限)
{
try
{
doService(request,response);
}
catch(Excetpion e)
{
記錄異常信息
}
}
}
protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws IOExcetion,ServletException;
//注意訪問(wèn)權(quán)限定義成protected,顯得既專業(yè),又嚴(yán)謹(jǐn),因?yàn)樗菍iT(mén)給子類用的
}
public class MyServlet1 extends BaseServlet
{
protected void doService(HttpServletRequest request, HttpServletResponse response) throws IOExcetion,ServletException
{
本Servlet只處理的具體業(yè)務(wù)邏輯代碼
}
}
父類方法中間的某段代碼不確定,留給子類干,就用模板方法設(shè)計(jì)模式。
備注:這道題的思路是先從總體解釋抽象類和接口的基本概念,然后再比較兩者的語(yǔ)法細(xì)節(jié),最后再說(shuō)兩者的應(yīng)用區(qū)別。比較兩者語(yǔ)法細(xì)節(jié)區(qū)別的條理是:先從一個(gè)類中的構(gòu)造方法、普通成員變量和方法(包括抽象方法),靜態(tài)變量和方法,繼承性等6個(gè)方面逐一去比較回答,接著從第三者繼承的角度的回答,特別是最后用了一個(gè)典型的例子來(lái)展現(xiàn)自己深厚的技術(shù)功底。
24、abstract的method是否可同時(shí)是static,是否可同時(shí)是native,是否可同時(shí)是synchronized?
abstract的method 不可以是static的,因?yàn)槌橄蟮姆椒ㄊ且蛔宇悓?shí)現(xiàn)的,而static與子類扯不上關(guān)系!
native方法表示該方法要用另外一種依賴平臺(tái)的編程語(yǔ)言實(shí)現(xiàn)的,不存在著被子類實(shí)現(xiàn)的問(wèn)題,所以,它也不能是抽象的,不能與abstract混用。例如,F(xiàn)ileOutputSteam類要硬件打交道,底層的實(shí)現(xiàn)用的是操作系統(tǒng)相關(guān)的api實(shí)現(xiàn),例如,在windows用c語(yǔ)言實(shí)現(xiàn)的,所以,查看jdk 的源代碼,可以發(fā)現(xiàn)FileOutputStream的open方法的定義如下:
private native void open(String name) throws FileNotFoundException;
如果我們要用java調(diào)用別人寫(xiě)的c語(yǔ)言函數(shù),我們是無(wú)法直接調(diào)用的,我們需要按照java的要求寫(xiě)一個(gè)c語(yǔ)言的函數(shù),又我們的這個(gè)c語(yǔ)言函數(shù)去調(diào)用別人的c語(yǔ)言函數(shù)。由于我們的c語(yǔ)言函數(shù)是按java的要求來(lái)寫(xiě)的,我們這個(gè)c語(yǔ)言函數(shù)就可以與java對(duì)接上,java那邊的對(duì)接方式就是定義出與我們這個(gè)c函數(shù)相對(duì)應(yīng)的方法,java中對(duì)應(yīng)的方法不需要寫(xiě)具體的代碼,但需要在前面聲明native。
關(guān)于synchronized與abstract合用的問(wèn)題,我覺(jué)得也不行,因?yàn)樵谖規(guī)啄甑膶W(xué)習(xí)和開(kāi)發(fā)中,從來(lái)沒(méi)見(jiàn)到過(guò)這種情況,并且我覺(jué)得synchronized應(yīng)該是作用在一個(gè)具體的方法上才有意義。
25、什么是內(nèi)部類?
內(nèi)部類就是在一個(gè)類的內(nèi)部定義的類,內(nèi)部類中不能定義靜態(tài)成員(我想可能是既然靜態(tài)成員類似c語(yǔ)言的全局變量,而內(nèi)部類通常是用于創(chuàng)建內(nèi)部對(duì)象用的,所以,把“全局變量”放在內(nèi)部類中就是毫無(wú)意義的事情,既然是毫無(wú)意義的事情,就應(yīng)該被禁止),內(nèi)部類可以直接訪問(wèn)外部類中的成員變量,內(nèi)部類可以定義在外部類的方法外面,也可以定義在外部類的方法體中,如下所示:
public class Outer
{
int out_x = 0;
public void method()
{
Inner1 inner1 = new Inner1();
class Inner2 //在方法體內(nèi)部定義的內(nèi)部類
{
public method()
{
out_x = 3;
}
}
Inner2 inner2 = new Inner2();
}
public class Inner1 //在方法體外面定義的內(nèi)部類
{
}
}
在方法體外面定義的內(nèi)部類的訪問(wèn)類型可以是public,protecte,默認(rèn)的,private等4種類型,這就好像類中定義的成員變量有4種訪問(wèn)類型一樣,它們決定這個(gè)內(nèi)部類的定義對(duì)其他類是否可見(jiàn);對(duì)于這種情況,我們也可以在外面創(chuàng)建內(nèi)部類的實(shí)例對(duì)象,創(chuàng)建內(nèi)部類的實(shí)例對(duì)象時(shí),一定要先創(chuàng)建外部類的實(shí)例對(duì)象,然后用這個(gè)外部類的實(shí)例對(duì)象去創(chuàng)建內(nèi)部類的實(shí)例對(duì)象,代碼如下:
Outer outer = new Outer();
Outer.Inner1 inner1 = outer.new Innner1();
在方法內(nèi)部定義的內(nèi)部類前面不能有訪問(wèn)類型修飾符,就好像方法中定義的局部變量一樣,但這種內(nèi)部類的前面可以使用final或abstract修飾符。這種內(nèi)部類對(duì)其他類是不可見(jiàn)的其他類無(wú)法引用這種內(nèi)部類,但是這種內(nèi)部類創(chuàng)建的實(shí)例對(duì)象可以傳遞給其他類訪問(wèn)。這種內(nèi)部類必須是先定義,后使用,即內(nèi)部類的定義代碼必須出現(xiàn)在使用該類之前,這與方法中的局部變量必須先定義后使用的道理也是一樣的。這種內(nèi)部類可以訪問(wèn)方法體中的局部變量,但是,該局部變量前必須加final修飾符。
對(duì)于這些細(xì)節(jié),只要在eclipse寫(xiě)代碼試試,根據(jù)開(kāi)發(fā)工具提示的各類錯(cuò)誤信息就可以馬上了解到。
在方法外部定義的內(nèi)部類前面可以加上static關(guān)鍵字,從而成為靜態(tài)內(nèi)部類,或者叫Static Nested Class。Static Nested Class與普通類在運(yùn)行時(shí)的行為和功能上沒(méi)有什么區(qū)別,只是在編程引用時(shí)的語(yǔ)法上有一些差別,它可以定義成public、protected、默認(rèn)的、private等多種類型,而普通類只能定義成public和默認(rèn)的這兩種類型。在外面引用Static Nested Class類的名稱為“外部類名.內(nèi)部類名”。在外面不需要?jiǎng)?chuàng)建外部類的實(shí)例對(duì)象,就可以直接創(chuàng)建Static Nested Class,例如,假設(shè)Inner是定義在Outer類中的Static Nested Class,那么可以使用如下語(yǔ)句創(chuàng)建Inner類:
Outer.Inner inner = new Outer.Inner();
由于static Nested Class不依賴于外部類的實(shí)例對(duì)象,所以,static Nested Class能訪問(wèn)外部類的非static成員變量。當(dāng)在外部類中訪問(wèn)Static Nested Class時(shí),可以直接使用Static Nested Class的名字,而不需要加上外部類的名字了,在Static Nested Class中也可以直接引用外部類的static的成員變量,不需要加上外部類的名字。
最后,在方法體內(nèi)部還可以采用如下語(yǔ)法來(lái)創(chuàng)建一種匿名內(nèi)部類,即定義某一接口或類的子類的同時(shí),還創(chuàng)建了該子類的實(shí)例對(duì)象,無(wú)需為該子類定義名稱:
public class Outer
{
public void start()
{
new Thread(
new Runable(){
public void run(){};
}
).start();
}
}
備注:首先根據(jù)你的印象說(shuō)出你對(duì)內(nèi)部類的總體方面的特點(diǎn):例如,在兩個(gè)地方可以定義,可以訪問(wèn)外部類的成員變量,不能定義靜態(tài)成員,這是大的特點(diǎn)。然后再說(shuō)一些細(xì)節(jié)方面的知識(shí),例如,幾種定義方式的語(yǔ)法區(qū)別,靜態(tài)內(nèi)部類,以及匿名內(nèi)部類。
26、內(nèi)部類可以引用他包含類的成員嗎?有沒(méi)有什么限制?
完全可以。如果不是靜態(tài)內(nèi)部類,那沒(méi)有什么限制!
如果你把靜態(tài)嵌套類當(dāng)作內(nèi)部類的一種特例,那在這種情況下不可以訪問(wèn)外部類的普通成員變量,而只能訪問(wèn)外部類中的靜態(tài)成員,例如,下面的代碼:
class Outer
{
static int x;
static class Inner
{
void test()
{
syso(x);
}
}
}
如果問(wèn)靜態(tài)內(nèi)部類能否訪問(wèn)外部類的成員這個(gè)問(wèn)題,該如何回答:
答題時(shí),也要能察言觀色,揣摩提問(wèn)者的心思,顯然人家希望你說(shuō)的是靜態(tài)內(nèi)部類不能訪問(wèn)外部類的成員,但你一上來(lái)就頂牛,這不好,要先順著人家,讓人家滿意,然后再說(shuō)特殊情況,讓人家吃驚。
27、Static Nested Class 和 Inner Class的不同。
參見(jiàn)前面的什么是內(nèi)部類的那道題
28、Anonymous Inner Class (匿名內(nèi)部類) 是否可以extends(繼承)其它類,是否可以implements(實(shí)現(xiàn))interface(接口)?
可以繼承其他類或?qū)崿F(xiàn)其他接口。
29、String是最基本的數(shù)據(jù)類型嗎?
基本數(shù)據(jù)類型包括byte、int、char、long、float、double、boolean和short。
java.lang.String類是final類型的,因此不可以繼承這個(gè)類、不能修改這個(gè)類。為了提高效率節(jié)省空間,我們應(yīng)該用StringBuffer類
30、String s = "Hello";s = s + " world!";這兩行代碼執(zhí)行后,原始的String對(duì)象中的內(nèi)容到底變了沒(méi)有?
沒(méi)有。因?yàn)镾tring被設(shè)計(jì)成不可變(immutable)類,所以它的所有對(duì)象都是不可變對(duì)象。在這段代碼中,s原先指向一個(gè)String對(duì)象,內(nèi)容是 "Hello",然后我們對(duì)s進(jìn)行了+操作,那么s所指向的那個(gè)對(duì)象是否發(fā)生了改變呢?答案是沒(méi)有。這時(shí),s不指向原來(lái)那個(gè)對(duì)象了,而指向了另一個(gè) String對(duì)象,內(nèi)容為"Hello world!",原來(lái)那個(gè)對(duì)象還存在于內(nèi)存之中,只是s這個(gè)引用變量不再指向它了。
通過(guò)上面的說(shuō)明,我們很容易導(dǎo)出另一個(gè)結(jié)論,如果經(jīng)常對(duì)字符串進(jìn)行各種各樣的修改,或者說(shuō),不可預(yù)見(jiàn)的修改,那么使用String來(lái)代表字符串的話會(huì)引起很大的內(nèi)存開(kāi)銷(xiāo)。因?yàn)?String對(duì)象建立之后不能再改變,所以對(duì)于每一個(gè)不同的字符串,都需要一個(gè)String對(duì)象來(lái)表示。這時(shí),應(yīng)該考慮使用StringBuffer類,它允許修改,而不是每個(gè)不同的字符串都要生成一個(gè)新的對(duì)象。并且,這兩種類的對(duì)象轉(zhuǎn)換十分容易。
同時(shí),我們還可以知道,如果要使用內(nèi)容相同的字符串,不必每次都new一個(gè)String。例如我們要在構(gòu)造器中對(duì)一個(gè)名叫s的String引用變量進(jìn)行初始化,把它設(shè)置為初始值,應(yīng)當(dāng)這樣做:
public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}
而非
s = new String("Initial Value");
后者每次都會(huì)調(diào)用構(gòu)造器,生成新對(duì)象,性能低下且內(nèi)存開(kāi)銷(xiāo)大,并且沒(méi)有意義,因?yàn)镾tring對(duì)象不可改變,所以對(duì)于內(nèi)容相同的字符串,只要一個(gè)String對(duì)象來(lái)表示就可以了。也就說(shuō),多次調(diào)用上面的構(gòu)造器創(chuàng)建多個(gè)對(duì)象,他們的String類型屬性s都指向同一個(gè)對(duì)象。
上面的結(jié)論還基于這樣一個(gè)事實(shí):對(duì)于字符串常量,如果內(nèi)容相同,Java認(rèn)為它們代表同一個(gè)String對(duì)象。而用關(guān)鍵字new調(diào)用構(gòu)造器,總是會(huì)創(chuàng)建一個(gè)新的對(duì)象,無(wú)論內(nèi)容是否相同。
至于為什么要把String類設(shè)計(jì)成不可變類,是它的用途決定的。其實(shí)不只String,很多Java標(biāo)準(zhǔn)類庫(kù)中的類都是不可變的。在開(kāi)發(fā)一個(gè)系統(tǒng)的時(shí)候,我們有時(shí)候也需要設(shè)計(jì)不可變類,來(lái)傳遞一組相關(guān)的值,這也是面向?qū)ο笏枷氲捏w現(xiàn)。不可變類有一些優(yōu)點(diǎn),比如因?yàn)樗膶?duì)象是只讀的,所以多線程并發(fā)訪問(wèn)也不會(huì)有任何問(wèn)題。當(dāng)然也有一些缺點(diǎn),比如每個(gè)不同的狀態(tài)都要一個(gè)對(duì)象來(lái)代表,可能會(huì)造成性能上的問(wèn)題。所以Java標(biāo)準(zhǔn)類庫(kù)還提供了一個(gè)可變版本,即 StringBuffer。
31、是否可以繼承String類?
String類是final類故不可以繼承。
32、String s = new String("xyz");創(chuàng)建了幾個(gè)String Object? 二者之間有什么區(qū)別?
兩個(gè),一個(gè)放在常量區(qū),不管寫(xiě)多少遍,都是同一個(gè)。New String每寫(xiě)一遍,就創(chuàng)建一個(gè)新。
33、String 和StringBuffer的區(qū)別
JAVA平臺(tái)提供了兩個(gè)類:String和StringBuffer,它們可以儲(chǔ)存和操作字符串,即包含多個(gè)字符的字符數(shù)據(jù)。這個(gè)String類提供了數(shù)值不可改變的字符串。而這個(gè)StringBuffer類提供的字符串進(jìn)行修改。當(dāng)你知道字符數(shù)據(jù)要改變的時(shí)候你就可以使用StringBuffer。典型地,你可以使用StringBuffers來(lái)動(dòng)態(tài)構(gòu)造字符數(shù)據(jù)。另外,String實(shí)現(xiàn)了equals方法,new String(“abc”).equals(new String(“abc”)的結(jié)果為true,而StringBuffer沒(méi)有實(shí)現(xiàn)equals方法,所以,new StringBuffer(“abc”).equals(new StringBuffer(“abc”)的結(jié)果為false。
接著要舉一個(gè)具體的例子來(lái)說(shuō)明,我們要把1到100的所有數(shù)字拼起來(lái),組成一個(gè)串。
StringBuffer sbf = new StringBuffer();
for(int i=0;i<100;i++)
{
sbf.append(i);
}
上面的代碼效率很高,因?yàn)橹粍?chuàng)建了一個(gè)StringBuffer對(duì)象,而下面的代碼效率很低,因?yàn)閯?chuàng)建了101個(gè)對(duì)象。
String str = new String();
for(int i=0;i<100;i++)
{
str = str + i;
}
34、如何把一段逗號(hào)分割的字符串轉(zhuǎn)換成一個(gè)數(shù)組?
如果不查jdk api,我很難寫(xiě)出來(lái)!我可以說(shuō)說(shuō)我的思路:
1. 用正則表達(dá)式,代碼大概為:String [] result = orgStr.split(“,”);
2. 用 StingTokenizer ,代碼為:StringTokenizer tokener = StringTokenizer(orgStr,”,”);
String [] result = new String[tokener .countTokens()];
Int i=0;
while(tokener.hasNext(){result[i++]=toker.nextToken();}
35、數(shù)組有沒(méi)有l(wèi)ength()這個(gè)方法? String有沒(méi)有l(wèi)ength()這個(gè)方法?
數(shù)組沒(méi)有l(wèi)ength()這個(gè)方法,有l(wèi)ength的屬性。String有有l(wèi)ength()這個(gè)方法。
36、try {}里有一個(gè)return語(yǔ)句,那么緊跟在這個(gè)try后的finally {}里的code會(huì)不會(huì)被執(zhí)行,什么時(shí)候被執(zhí)行,在return前還是后?
會(huì)執(zhí)行,在return前執(zhí)行。
我的答案是在return中間執(zhí)行,參看下一題的講解。
public class Test {
/**
* @param args add by zxx ,Dec 9, 2008
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(new Test().test());;
}
static int test()
{
int x = 1;
try
{
return x;
}
finally
{
++x;
}
}
}
---------執(zhí)行結(jié)果 ---------
1
37、下面的程序代碼輸出的結(jié)果是多少?
public class smallT
{
public static void main(String args[])
{
smallT t = new smallT();
int b = t.get();
System.out.println(b);
}
public int get()
{
try
{
return 1 ;
}
finally
{
return 2 ;
}
}
}
返回的結(jié)果是2。
我可以通過(guò)下面一個(gè)例子程序來(lái)幫助我解釋這個(gè)答案,從下面例子的運(yùn)行結(jié)果中可以發(fā)現(xiàn),try中的return語(yǔ)句調(diào)用的函數(shù)先于finally中調(diào)用的函數(shù)執(zhí)行,也就是說(shuō)return語(yǔ)句先執(zhí)行,finally語(yǔ)句后執(zhí)行,所以,返回的結(jié)果是2。Return并不是讓函數(shù)馬上返回,而是return語(yǔ)句執(zhí)行后,將把返回結(jié)果放置進(jìn)函數(shù)棧中,此時(shí)函數(shù)并不是馬上返回,它要執(zhí)行finally語(yǔ)句后才真正開(kāi)始返回。
在講解答案時(shí)可以用下面的程序來(lái)幫助分析:
public class Test {
/**
* @param args add by zxx ,Dec 9, 2008
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(new Test().test());;
}
int test()
{
try
{
return func1();
}
finally
{
return func2();
}
}
int func1()
{
System.out.println("func1");
return 1;
}
int func2()
{
System.out.println("func2");
return 2;
}
}
-----------執(zhí)行結(jié)果-----------------
func1
func2
2
結(jié)論:finally中的代碼比return 和break語(yǔ)句后執(zhí)行
38、final, finally, finalize的區(qū)別。
final 用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。
內(nèi)部類要訪問(wèn)局部變量,局部變量必須定義成final類型,例如,一段代碼……
finally是異常處理語(yǔ)句結(jié)構(gòu)的一部分,表示總是執(zhí)行。
finalize是Object類的一個(gè)方法,在垃圾收集器執(zhí)行的時(shí)候會(huì)調(diào)用被回收對(duì)象的此方法,可以覆蓋此方法提供垃圾收集時(shí)的其他資源回收,例如關(guān)閉文件等。JVM不保證此方法總被調(diào)用
39、運(yùn)行時(shí)異常與一般異常有何異同?
異常表示程序運(yùn)行過(guò)程中可能出現(xiàn)的非正常狀態(tài),運(yùn)行時(shí)異常表示虛擬機(jī)的通常操作中可能遇到的異常,是一種常見(jiàn)運(yùn)行錯(cuò)誤。java編譯器要求方法必須聲明拋出可能發(fā)生的非運(yùn)行時(shí)異常,但是并不要求必須聲明拋出未被捕獲的運(yùn)行時(shí)異常。
40、error和exception有什么區(qū)別?
error 表示恢復(fù)不是不可能但很困難的情況下的一種嚴(yán)重問(wèn)題。比如說(shuō)內(nèi)存溢出。不可能指望程序能處理這樣的情況。 exception 表示一種設(shè)計(jì)或?qū)崿F(xiàn)問(wèn)題。也就是說(shuō),它表示如果程序運(yùn)行正常,從不會(huì)發(fā)生的情況。
41、Java中的異常處理機(jī)制的簡(jiǎn)單原理和應(yīng)用。
當(dāng)JAVA程序違反了JAVA的語(yǔ)義規(guī)則時(shí),JAVA虛擬機(jī)就會(huì)將發(fā)生的錯(cuò)誤表示為一個(gè)異常。違反語(yǔ)義規(guī)則包括2種情況。一種是JAVA類庫(kù)內(nèi)置的語(yǔ)義檢查。例如數(shù)組下標(biāo)越界,會(huì)引發(fā)IndexOutOfBoundsException;訪問(wèn)null的對(duì)象時(shí)會(huì)引發(fā)NullPointerException。另一種情況就是JAVA允許程序員擴(kuò)展這種語(yǔ)義檢查,程序員可以創(chuàng)建自己的異常,并自由選擇在何時(shí)用throw關(guān)鍵字引發(fā)異常。所有的異常都是java.lang.Thowable的子類。
42、給我一個(gè)你最常見(jiàn)到的runtime exception。
ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFORMatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException
43、JAVA語(yǔ)言如何進(jìn)行異常處理,關(guān)鍵字:throws,throw,try,catch,finally分別代表什么意義?在try塊中可以拋出異常嗎?
Java通過(guò)面向?qū)ο蟮姆椒ㄟM(jìn)行異常處理,把各種不同的異常進(jìn)行分類,并提供了良好的接口。在Java中,每個(gè)異常都是一個(gè)對(duì)象,它是Throwable類或其它子類的實(shí)例。當(dāng)一個(gè)方法出現(xiàn)異常后便拋出一個(gè)異常對(duì)象,該對(duì)象中包含有異常信息,調(diào)用這個(gè)對(duì)象的方法可以捕獲到這個(gè)異常并進(jìn)行處理。Java的異常處理是通過(guò)5個(gè)關(guān)鍵詞來(lái)實(shí)現(xiàn)的:try、catch、throw、throws和finally。一般情況下是用try來(lái)執(zhí)行一段程序,如果出現(xiàn)異常,系統(tǒng)會(huì)拋出(throws)一個(gè)異常,這時(shí)候你可以通過(guò)它的類型來(lái)捕捉(catch)它,或最后(finally)由缺省處理器來(lái)處理。
用try來(lái)指定一塊預(yù)防所有"異常"的程序。緊跟在try程序后面,應(yīng)包含一個(gè)catch子句來(lái)指定你想要捕捉的"異常"的類型。
throw語(yǔ)句用來(lái)明確地拋出一個(gè)"異常"。
throws用來(lái)標(biāo)明一個(gè)成員函數(shù)可能拋出的各種"異常"。
Finally為確保一段代碼不管發(fā)生什么"異常"都被執(zhí)行一段代碼。
可以在一個(gè)成員函數(shù)調(diào)用的外面寫(xiě)一個(gè)try語(yǔ)句,在這個(gè)成員函數(shù)內(nèi)部寫(xiě)另一個(gè)try語(yǔ)句保護(hù)其他代碼。每當(dāng)遇到一個(gè)try語(yǔ)句,"異常"的框架就放到堆棧上面,直到所有的try語(yǔ)句都完成。如果下一級(jí)的try語(yǔ)句沒(méi)有對(duì)某種"異常"進(jìn)行處理,堆棧就會(huì)展開(kāi),直到遇到有處理這種"異常"的try語(yǔ)句。
44、java中有幾種方法可以實(shí)現(xiàn)一個(gè)線程?用什么關(guān)鍵字修飾同步方法? stop()和suspend()方法為何不推薦使用?
有兩種實(shí)現(xiàn)方法,分別使用new Thread()和new Thread(runnable)形式,第一種直接調(diào)用thread的run方法,所以,我們往往使用Thread子類,即new SubThread()。第二種調(diào)用runnable的run方法。
有兩種實(shí)現(xiàn)方法,分別是繼承Thread類與實(shí)現(xiàn)Runnable接口
用synchronized關(guān)鍵字修飾同步方法
反對(duì)使用stop(),是因?yàn)樗话踩?。它?huì)解除由線程獲取的所有鎖定,而且如果對(duì)象處于一種不連貫狀態(tài),那么其他線程能在那種狀態(tài)下檢查和修改它們。結(jié)果很難檢查出真正的問(wèn)題所在。suspend()方法容易發(fā)生死鎖。調(diào)用suspend()的時(shí)候,目標(biāo)線程會(huì)停下來(lái),但卻仍然持有在這之前獲得的鎖定。此時(shí),其他任何線程都不能訪問(wèn)鎖定的資源,除非被"掛起"的線程恢復(fù)運(yùn)行。對(duì)任何線程來(lái)說(shuō),如果它們想恢復(fù)目標(biāo)線程,同時(shí)又試圖使用任何一個(gè)鎖定的資源,就會(huì)造成死鎖。所以不應(yīng)該使用suspend(),而應(yīng)在自己的Thread類中置入一個(gè)標(biāo)志,指出線程應(yīng)該活動(dòng)還是掛起。若標(biāo)志指出線程應(yīng)該掛起,便用wait()命其進(jìn)入等待狀態(tài)。若標(biāo)志指出線程應(yīng)當(dāng)恢復(fù),則用一個(gè)notify()重新啟動(dòng)線程。
45、sleep() 和 wait() 有什么區(qū)別?
(網(wǎng)上的答案:sleep是線程類(Thread)的方法,導(dǎo)致此線程暫停執(zhí)行指定時(shí)間,給執(zhí)行機(jī)會(huì)給其他線程,但是監(jiān)控狀態(tài)依然保持,到時(shí)后會(huì)自動(dòng)恢復(fù)。調(diào)用sleep不會(huì)釋放對(duì)象鎖。 wait是Object類的方法,對(duì)此對(duì)象調(diào)用wait方法導(dǎo)致本線程放棄對(duì)象鎖,進(jìn)入等待此對(duì)象的等待鎖定池,只有針對(duì)此對(duì)象發(fā)出notify方法(或notifyAll)后本線程才進(jìn)入對(duì)象鎖定池準(zhǔn)備獲得對(duì)象鎖進(jìn)入運(yùn)行狀態(tài)。)
sleep就是正在執(zhí)行的線程主動(dòng)讓出cpu,cpu去執(zhí)行其他線程,在sleep指定的時(shí)間過(guò)后,cpu才會(huì)回到這個(gè)線程上繼續(xù)往下執(zhí)行,如果當(dāng)前線程進(jìn)入了同步鎖,sleep方法并不會(huì)釋放鎖,即使當(dāng)前線程使用sleep方法讓出了cpu,但其他被同步鎖擋住了的線程也無(wú)法得到執(zhí)行。wait是指在一個(gè)已經(jīng)進(jìn)入了同步鎖的線程內(nèi),讓自己暫時(shí)讓出同步鎖,以便其他正在等待此鎖的線程可以得到同步鎖并運(yùn)行,只有其他線程調(diào)用了notify方法(notify并不釋放鎖,只是告訴調(diào)用過(guò)wait方法的線程可以去參與獲得鎖的競(jìng)爭(zhēng)了,但不是馬上得到鎖,因?yàn)殒i還在別人手里,別人還沒(méi)釋放。如果notify方法后面的代碼還有很多,需要這些代碼執(zhí)行完后才會(huì)釋放鎖,可以在notfiy方法后增加一個(gè)等待和一些代碼,看看效果),調(diào)用wait方法的線程就會(huì)解除wait狀態(tài)和程序可以再次得到鎖后繼續(xù)向下運(yùn)行。對(duì)于wait的講解一定要配合例子代碼來(lái)說(shuō)明,才顯得自己真明白。
package com.huawei.interview;
public class MultiThread {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new Thread(new Thread1()).start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Thread(new Thread2()).start();
}
private static class Thread1 implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
//由于這里的Thread1和下面的Thread2內(nèi)部run方法要用同一對(duì)象作為監(jiān)視器,我們這里不能用this,因?yàn)樵赥hread2里面的this和這個(gè)Thread1的this不是同一個(gè)對(duì)象。我們用MultiThread.class這個(gè)字節(jié)碼對(duì)象,當(dāng)前虛擬機(jī)里引用這個(gè)變量時(shí),指向的都是同一個(gè)對(duì)象。
synchronized (MultiThread.class) {
System.out.println("enter thread1...");
System.out.println("thread1 is waiting");
try {
//釋放鎖有兩種方式,第一種方式是程序自然離開(kāi)監(jiān)視器的范圍,也就是離開(kāi)了synchronized關(guān)鍵字管轄的代碼范圍,另一種方式就是在synchronized關(guān)鍵字管轄的代碼內(nèi)部調(diào)用監(jiān)視器對(duì)象的wait方法。這里,使用wait方法釋放鎖。
MultiThread.class.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("thread1 is going on...");
System.out.println("thread1 is being over!");
}
}
}
private static class Thread2 implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (MultiThread.class) {
System.out.println("enter thread2...");
System.out.println("thread2 notify other thread can release wait status..");
//由于notify方法并不釋放鎖, 即使thread2調(diào)用下面的sleep方法休息了10毫秒,但thread1仍然不會(huì)執(zhí)行,因?yàn)閠hread2沒(méi)有釋放鎖,所以Thread1無(wú)法得不到鎖。
MultiThread.class.notify();
System.out.println("thread2 is sleeping ten millisecond...");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("thread2 is going on...");
System.out.println("thread2 is being over!");
}
}
}
}
46、同步和異步有何異同,在什么情況下分別使用他們?舉例說(shuō)明。
如果數(shù)據(jù)將在線程間共享。例如正在寫(xiě)的數(shù)據(jù)以后可能被另一個(gè)線程讀到,或者正在讀的數(shù)據(jù)可能已經(jīng)被另一個(gè)線程寫(xiě)過(guò)了,那么這些數(shù)據(jù)就是共享數(shù)據(jù),必須進(jìn)行同步存取。
當(dāng)應(yīng)用程序在對(duì)象上調(diào)用了一個(gè)需要花費(fèi)很長(zhǎng)時(shí)間來(lái)執(zhí)行的方法,并且不希望讓程序等待方法的返回時(shí),就應(yīng)該使用異步編程,在很多情況下采用異步途徑往往更有效率。
47. 下面兩個(gè)方法同步嗎?(自己發(fā)明)
class Test
{
synchronized static void sayHello3()
{
}
synchronized void getX(){}
}
48、多線程有幾種實(shí)現(xiàn)方法?同步有幾種實(shí)現(xiàn)方法?
多線程有兩種實(shí)現(xiàn)方法,分別是繼承Thread類與實(shí)現(xiàn)Runnable接口
同步的實(shí)現(xiàn)方面有兩種,分別是synchronized,wait與notify
wait():使一個(gè)線程處于等待狀態(tài),并且釋放所持有的對(duì)象的lock。
sleep():使一個(gè)正在運(yùn)行的線程處于睡眠狀態(tài),是一個(gè)靜態(tài)方法,調(diào)用此方法要捕捉InterruptedException異常。
notify():喚醒一個(gè)處于等待狀態(tài)的線程,注意的是在調(diào)用此方法的時(shí)候,并不能確切的喚醒某一個(gè)等待狀態(tài)的線程,而是由JVM確定喚醒哪個(gè)線程,而且不是按優(yōu)先級(jí)。
Allnotity():喚醒所有處入等待狀態(tài)的線程,注意并不是給所有喚醒線程一個(gè)對(duì)象的鎖,而是讓它們競(jìng)爭(zhēng)。
49、啟動(dòng)一個(gè)線程是用run()還是start()? .
啟動(dòng)一個(gè)線程是調(diào)用start()方法,使線程就緒狀態(tài),以后可以被調(diào)度為運(yùn)行狀態(tài),一個(gè)線程必須關(guān)聯(lián)一些具體的執(zhí)行代碼,run()方法是該線程所關(guān)聯(lián)的執(zhí)行代碼。
47、當(dāng)一個(gè)線程進(jìn)入一個(gè)對(duì)象的一個(gè)synchronized方法后,其它線程是否可進(jìn)入此對(duì)象的其它方法?
分幾種情況:
1.其他方法前是否加了synchronized關(guān)鍵字,如果沒(méi)加,則能。
2.如果這個(gè)方法內(nèi)部調(diào)用了wait,則可以進(jìn)入其他synchronized方法。
3.如果其他個(gè)方法都加了synchronized關(guān)鍵字,并且內(nèi)部沒(méi)有調(diào)用wait,則不能。
50、線程的基本概念、線程的基本狀態(tài)以及狀態(tài)之間的關(guān)系
一個(gè)程序中可以有多條執(zhí)行線索同時(shí)執(zhí)行,一個(gè)線程就是程序中的一條執(zhí)行線索,每個(gè)線程上都關(guān)聯(lián)有要執(zhí)行的代碼,即可以有多段程序代碼同時(shí)運(yùn)行,每個(gè)程序至少都有一個(gè)線程,即main方法執(zhí)行的那個(gè)線程。如果只是一個(gè)cpu,它怎么能夠同時(shí)執(zhí)行多段程序呢?這是從宏觀上來(lái)看的,cpu一會(huì)執(zhí)行a線索,一會(huì)執(zhí)行b線索,切換時(shí)間很快,給人的感覺(jué)是a,b在同時(shí)執(zhí)行,好比大家在同一個(gè)辦公室上網(wǎng),只有一條鏈接到外部網(wǎng)線,其實(shí),這條網(wǎng)線一會(huì)為a傳數(shù)據(jù),一會(huì)為b傳數(shù)據(jù),由于切換時(shí)間很短暫,所以,大家感覺(jué)都在同時(shí)上網(wǎng)。
狀態(tài):就緒,運(yùn)行,synchronize阻塞,wait和sleep掛起,結(jié)束。wait必須在synchronized內(nèi)部調(diào)用。
調(diào)用線程的start方法后線程進(jìn)入就緒狀態(tài),線程調(diào)度系統(tǒng)將就緒狀態(tài)的線程轉(zhuǎn)為運(yùn)行狀態(tài),遇到synchronized語(yǔ)句時(shí),由運(yùn)行狀態(tài)轉(zhuǎn)為阻塞,當(dāng)synchronized獲得鎖后,由阻塞轉(zhuǎn)為運(yùn)行,在這種情況可以調(diào)用wait方法轉(zhuǎn)為掛起狀態(tài),當(dāng)線程關(guān)聯(lián)的代碼執(zhí)行完后,線程變?yōu)榻Y(jié)束狀態(tài)。
51、簡(jiǎn)述synchronized和java.util.concurrent.locks.Lock的異同 ?
主要相同點(diǎn):Lock能完成synchronized所實(shí)現(xiàn)的所有功能
主要不同點(diǎn):Lock有比synchronized更精確的線程語(yǔ)義和更好的性能。synchronized會(huì)自動(dòng)釋放鎖,而Lock一定要求程序員手工釋放,并且必須在finally從句中釋放。Lock還有更強(qiáng)大的功能,例如,它的tryLock方法可以非阻塞方式去拿鎖。
舉例說(shuō)明(對(duì)下面的題用lock進(jìn)行了改寫(xiě)):
package com.huawei.interview;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadTest {
/**
* @param args
*/
private int j;
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadTest tt = new ThreadTest();
for(int i=0;i<2;i++)
{
new Thread(tt.new adder()).start();
new Thread(tt.new subtractor()).start();
}
}
private class subtractor implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
while(true)
{
/*synchronized (ThreadTest.this) {
System.out.println("j--=" + j--);
//這里拋異常了,鎖能釋放嗎?
}*/
lock.lock();
try
{
System.out.println("j--=" + j--);
}finally
{
lock.unlock();
}
}
}
}
private class adder implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
while(true)
{
/*synchronized (ThreadTest.this) {
System.out.println("j++=" + j++);
}*/
lock.lock();
try
{
System.out.println("j++=" + j++);
}finally
{
lock.unlock();
}
}
}
}
}
52、設(shè)計(jì)4個(gè)線程,其中兩個(gè)線程每次對(duì)j增加1,另外兩個(gè)線程對(duì)j每次減少1。寫(xiě)出程序。
以下程序使用內(nèi)部類實(shí)現(xiàn)線程,對(duì)j增減的時(shí)候沒(méi)有考慮順序問(wèn)題。
public class ThreadTest1
{
private int j;
public static void main(String args[]){
ThreadTest1 tt=new ThreadTest1();
Inc inc=tt.new Inc();
Dec dec=tt.new Dec();
for(int i=0;i<2;i++){
Thread t=new Thread(inc);
t.start();
t=new Thread(dec);
t.start();
}
}
private synchronized void inc(){
j++;
System.out.println(Thread.currentThread().getName()+"-inc:"+j);
}
private synchronized void dec(){
j--;
System.out.println(Thread.currentThread().getName()+"-dec:"+j);
}
class Inc implements Runnable{
public void run(){
for(int i=0;i<100;i++){
inc();
}
}
}
class Dec implements Runnable{
public void run(){
for(int i=0;i<100;i++){
dec();
}
}
}
}
53、ArrayList和Vector的區(qū)別
答:
這兩個(gè)類都實(shí)現(xiàn)了List接口(List接口繼承了Collection接口),他們都是有序集合,即存儲(chǔ)在這兩個(gè)集合中的元素的位置都是有順序的,相當(dāng)于一種動(dòng)態(tài)的數(shù)組,我們以后可以按位置索引號(hào)取出某個(gè)元素,,并且其中的數(shù)據(jù)是允許重復(fù)的,這是HashSet之類的集合的最大不同處,HashSet之類的集合不可以按索引號(hào)去檢索其中的元素,也不允許有重復(fù)的元素(本來(lái)題目問(wèn)的與hashset沒(méi)有任何關(guān)系,但為了說(shuō)清楚ArrayList與Vector的功能,我們使用對(duì)比方式,更有利于說(shuō)明問(wèn)題)。
接著才說(shuō)ArrayList與Vector的區(qū)別,這主要包括兩個(gè)方面:.
(1)同步性:
Vector是線程安全的,也就是說(shuō)是它的方法之間是線程同步的,而ArrayList是線程序不安全的,它的方法之間是線程不同步的。如果只有一個(gè)線程會(huì)訪問(wèn)到集合,那最好是使用ArrayList,因?yàn)樗豢紤]線程安全,效率會(huì)高些;如果有多個(gè)線程會(huì)訪問(wèn)到集合,那最好是使用Vector,因?yàn)椴恍枰覀冏约涸偃タ紤]和編寫(xiě)線程安全的代碼。
(2)數(shù)據(jù)增長(zhǎng):
ArrayList與Vector都有一個(gè)初始的容量大小,當(dāng)存儲(chǔ)進(jìn)它們里面的元素的個(gè)數(shù)超過(guò)了容量時(shí),就需要增加ArrayList與Vector的存儲(chǔ)空間,每次要增加存儲(chǔ)空間時(shí),不是只增加一個(gè)存儲(chǔ)單元,而是增加多個(gè)存儲(chǔ)單元,每次增加的存儲(chǔ)單元的個(gè)數(shù)在內(nèi)存空間利用與程序效率之間要取得一定的平衡。Vector默認(rèn)增長(zhǎng)為原來(lái)兩倍,而ArrayList的增長(zhǎng)策略在文檔中沒(méi)有明確規(guī)定(從源代碼看到的是增長(zhǎng)為原來(lái)的1.5倍)。ArrayList與Vector都可以設(shè)置初始的空間大小,Vector還可以設(shè)置增長(zhǎng)的空間大小,而ArrayList沒(méi)有提供設(shè)置增長(zhǎng)空間的方法。
54、HashMap和Hashtable的區(qū)別
(條理上還需要整理,也是先說(shuō)相同點(diǎn),再說(shuō)不同點(diǎn))
HashMap是Hashtable的輕量級(jí)實(shí)現(xiàn)(非線程安全的實(shí)現(xiàn)),他們都完成了Map接口,主要區(qū)別在于HashMap允許空(null)鍵值(key),由于非線程安全,在只有一個(gè)線程訪問(wèn)的情況下,效率要高于Hashtable。
HashMap允許將null作為一個(gè)entry的key或者value,而Hashtable不允許。
HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因?yàn)閏ontains方法容易讓人引起誤解。
Hashtable繼承自Dictionary類,而HashMap是Java1.2引進(jìn)的Map interface的一個(gè)實(shí)現(xiàn)。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多個(gè)線程訪問(wèn)Hashtable時(shí),不需要自己為它的方法實(shí)現(xiàn)同步,而HashMap 就必須為之提供外同步。
Hashtable和HashMap采用的hash/rehash算法都大概一樣,所以性能不會(huì)有很大的差異。
就HashMap與HashTable主要從三方面來(lái)說(shuō)。
一.歷史原因:Hashtable是基于陳舊的Dictionary類的,HashMap是Java 1.2引進(jìn)的Map接口的一個(gè)實(shí)現(xiàn)
二.同步性:Hashtable是線程安全的,也就是說(shuō)是同步的,而HashMap是線程序不安全的,不是同步的
三.值:只有HashMap可以讓你將空值作為一個(gè)表的條目的key或value
55、List 和 Map 區(qū)別?
一個(gè)是存儲(chǔ)單列數(shù)據(jù)的集合,另一個(gè)是存儲(chǔ)鍵和值這樣的雙列數(shù)據(jù)的集合,List中存儲(chǔ)的數(shù)據(jù)是有順序,并且允許重復(fù);Map中存儲(chǔ)的數(shù)據(jù)是沒(méi)有順序的,其鍵是不能重復(fù)的,它的值是可以有重復(fù)的。
56、List, Set, Map是否繼承自Collection接口?
List,Set是,Map不是
57、List、Map、Set三個(gè)接口,存取元素時(shí),各有什么特點(diǎn)?
List 以特定次序來(lái)持有元素,可有重復(fù)元素。Set 無(wú)法擁有重復(fù)元素,內(nèi)部排序。Map 保存key-value值,value可多值。
HashSet按照hashcode值的某種運(yùn)算方式進(jìn)行存儲(chǔ),而不是直接按hashCode值的大小進(jìn)行存儲(chǔ)。例如,"abc" ---> 78,"def" ---> 62,"xyz" ---> 65在hashSet中的存儲(chǔ)順序不是62,65,78,這些問(wèn)題感謝以前一個(gè)叫崔健的學(xué)員提出,最后通過(guò)查看源代碼給他解釋清楚,看本次培訓(xùn)學(xué)員當(dāng)中有多少能看懂源碼。LinkedHashSet按插入的順序存儲(chǔ),那被存儲(chǔ)對(duì)象的hashcode方法還有什么作用呢?學(xué)員想想!hashset集合比較兩個(gè)對(duì)象是否相等,首先看hashcode方法是否相等,然后看equals方法是否相等。new 兩個(gè)Student插入到HashSet中,看HashSet的size,實(shí)現(xiàn)hashcode和equals方法后再看size。
同一個(gè)對(duì)象可以在Vector中加入多次。往集合里面加元素,相當(dāng)于集合里用一根繩子連接到了目標(biāo)對(duì)象。往HashSet中卻加不了多次的。
58、說(shuō)出ArrayList,Vector, LinkedList的存儲(chǔ)性能和特性
ArrayList和Vector都是使用數(shù)組方式存儲(chǔ)數(shù)據(jù),此數(shù)組元素?cái)?shù)大于實(shí)際存儲(chǔ)的數(shù)據(jù)以便增加和插入元素,它們都允許直接按序號(hào)索引元素,但是插入元素要涉及數(shù)組元素移動(dòng)等內(nèi)存操作,所以索引數(shù)據(jù)快而插入數(shù)據(jù)慢,Vector由于使用了synchronized方法(線程安全),通常性能上較ArrayList差,而LinkedList使用雙向鏈表實(shí)現(xiàn)存儲(chǔ),按序號(hào)索引數(shù)據(jù)需要進(jìn)行前向或后向遍歷,但是插入數(shù)據(jù)時(shí)只需要記錄本項(xiàng)的前后項(xiàng)即可,所以插入速度較快。
LinkedList也是線程不安全的,LinkedList提供了一些方法,使得LinkedList可以被當(dāng)作堆棧和隊(duì)列來(lái)使用。
59、去掉一個(gè)Vector集合中重復(fù)的元素
Vector newVector = new Vector();
For (int i=0;i<vector.size();i++)
{
Object obj = vector.get(i);
if(!newVector.contains(obj);
newVector.add(obj);
}
還有一種簡(jiǎn)單的方式,HashSet set = new HashSet(vector);
60、Collection 和 Collections的區(qū)別。
Collection是集合類的上級(jí)接口,繼承與他的接口主要有Set 和List.
Collections是針對(duì)集合類的一個(gè)幫助類,他提供一系列靜態(tài)方法實(shí)現(xiàn)對(duì)各種集合的搜索、排序、線程安全化等操作。
61、Set里的元素是不能重復(fù)的,那么用什么方法來(lái)區(qū)分重復(fù)與否呢? 是用==還是equals()? 它們有何區(qū)別?
Set里的元素是不能重復(fù)的,元素重復(fù)與否是使用equals()方法進(jìn)行判斷的。
equals()和==方法決定引用值是否指向同一對(duì)象equals()在類中被覆蓋,為的是當(dāng)兩個(gè)分離的對(duì)象的內(nèi)容和類型相配的話,返回真值。
62、你所知道的集合類都有哪些?主要方法?
最常用的集合類是 List 和 Map。 List 的具體實(shí)現(xiàn)包括 ArrayList 和 Vector,它們是可變大小的列表,比較適合構(gòu)建、存儲(chǔ)和操作任何類型對(duì)象的元素列表。 List 適用于按數(shù)值索引訪問(wèn)元素的情形。
Map 提供了一個(gè)更通用的元素存儲(chǔ)方法。 Map 集合類用于存儲(chǔ)元素對(duì)(稱作"鍵"和"值"),其中每個(gè)鍵映射到一個(gè)值。
ArrayList/VectoràList
àCollection
HashSet/TreeSetàSet
PropetiesàHashTable
àMap
Treemap/HashMap
我記的不是方法名,而是思想,我知道它們都有增刪改查的方法,但這些方法的具體名稱,我記得不是很清楚,對(duì)于set,大概的方法是add,remove, contains;對(duì)于map,大概的方法就是put,remove,contains等,因?yàn)?,我只要在eclispe下按點(diǎn)操作符,很自然的這些方法就出來(lái)了。我記住的一些思想就是List類會(huì)有g(shù)et(int index)這樣的方法,因?yàn)樗梢园错樞蛉≡?,而set類中沒(méi)有g(shù)et(int index)這樣的方法。List和set都可以迭代出所有元素,迭代時(shí)先要得到一個(gè)iterator對(duì)象,所以,set和list類都有一個(gè)iterator方法,用于返回那個(gè)iterator對(duì)象。map可以返回三個(gè)集合,一個(gè)是返回所有的key的集合,另外一個(gè)返回的是所有value的集合,再一個(gè)返回的key和value組合成的EntrySet對(duì)象的集合,map也有g(shù)et方法,參數(shù)是key,返回值是key對(duì)應(yīng)的value。
63、兩個(gè)對(duì)象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對(duì)不對(duì)?
對(duì)。
如果對(duì)象要保存在HashSet或HashMap中,它們的equals相等,那么,它們的hashcode值就必須相等。
如果不是要保存在HashSet或HashMap,則與hashcode沒(méi)有什么關(guān)系了,這時(shí)候hashcode不等是可以的,例如arrayList存儲(chǔ)的對(duì)象就不用實(shí)現(xiàn)hashcode,當(dāng)然,我們沒(méi)有理由不實(shí)現(xiàn),通常都會(huì)去實(shí)現(xiàn)的。
64、java中有幾種類型的流?JDK為每種類型的流提供了一些抽象類以供繼承,請(qǐng)說(shuō)出他們分別是哪些類?
字節(jié)流,字符流。字節(jié)流繼承于InputStream OutputStream,字符流繼承于InputStreamReader OutputStreamWriter。在java.io包中還有許多其他的流,主要是為了提高性能和使用方便。
65、什么是java序列化,如何實(shí)現(xiàn)java序列化?
我們有時(shí)候?qū)⒁粋€(gè)java對(duì)象變成字節(jié)流的形式傳出去或者從一個(gè)字節(jié)流中恢復(fù)成一個(gè)java對(duì)象,例如,要將java對(duì)象存儲(chǔ)到硬盤(pán)或者傳送給網(wǎng)絡(luò)上的其他計(jì)算機(jī),這個(gè)過(guò)程我們可以自己寫(xiě)代碼去把一個(gè)java對(duì)象變成某個(gè)格式的字節(jié)流再傳輸,但是,jre本身就提供了這種支持,我們可以調(diào)用OutputStream的writeObject方法來(lái)做,如果要讓java 幫我們做,要被傳輸?shù)膶?duì)象必須實(shí)現(xiàn)serializable接口,這樣,javac編譯時(shí)就會(huì)進(jìn)行特殊處理,編譯的類才可以被writeObject方法操作,這就是所謂的序列化。需要被序列化的類必須實(shí)現(xiàn)Serializable接口,該接口是一個(gè)mini接口,其中沒(méi)有需要實(shí)現(xiàn)的方法,implements Serializable只是為了標(biāo)注該對(duì)象是可被序列化的。
例如,在web開(kāi)發(fā)中,如果對(duì)象被保存在了Session中,tomcat在重啟時(shí)要把Session對(duì)象序列化到硬盤(pán),這個(gè)對(duì)象就必須實(shí)現(xiàn)Serializable接口。如果對(duì)象要經(jīng)過(guò)分布式系統(tǒng)進(jìn)行網(wǎng)絡(luò)傳輸或通過(guò)rmi等遠(yuǎn)程調(diào)用,這就需要在網(wǎng)絡(luò)上傳輸對(duì)象,被傳輸?shù)膶?duì)象就必須實(shí)現(xiàn)Serializable接口。
66、描述一下JVM加載class文件的原理機(jī)制?
JVM中類的裝載是由ClassLoader和它的子類來(lái)實(shí)現(xiàn)的,Java ClassLoader 是一個(gè)重要的Java運(yùn)行時(shí)系統(tǒng)組件。它負(fù)責(zé)在運(yùn)行時(shí)查找和裝入類文件的類。
67、heap和stack有什么區(qū)別。
java的內(nèi)存分為兩類,一類是棧內(nèi)存,一類是堆內(nèi)存。棧內(nèi)存是指程序進(jìn)入一個(gè)方法時(shí),會(huì)為這個(gè)方法單獨(dú)分配一塊私屬存儲(chǔ)空間,用于存儲(chǔ)這個(gè)方法內(nèi)部的局部變量,當(dāng)這個(gè)方法結(jié)束時(shí),分配給這個(gè)方法的棧會(huì)釋放,這個(gè)棧中的變量也將隨之釋放。
堆是與棧作用不同的內(nèi)存,一般用于存放不放在當(dāng)前方法棧中的那些數(shù)據(jù),例如,使用new創(chuàng)建的對(duì)象都放在堆里,所以,它不會(huì)隨方法的結(jié)束而消失。方法中的局部變量使用final修飾后,放在堆中,而不是棧中。
68、GC是什么? 為什么要有GC?
GC是垃圾收集的意思(Gabage Collection),內(nèi)存處理是編程人員容易出現(xiàn)問(wèn)題的地方,忘記或者錯(cuò)誤的內(nèi)存回收會(huì)導(dǎo)致程序或系統(tǒng)的不穩(wěn)定甚至崩潰,Java提供的GC功能可以自動(dòng)監(jiān)測(cè)對(duì)象是否超過(guò)作用域從而達(dá)到自動(dòng)回收內(nèi)存的目的,Java語(yǔ)言沒(méi)有提供釋放已分配內(nèi)存的顯示操作方法。
69、垃圾回收的優(yōu)點(diǎn)和原理。并考慮2種回收機(jī)制。
Java語(yǔ)言中一個(gè)顯著的特點(diǎn)就是引入了垃圾回收機(jī)制,使c++程序員最頭疼的內(nèi)存管理的問(wèn)題迎刃而解,它使得Java程序員在編寫(xiě)程序的時(shí)候不再需要考慮內(nèi)存管理。由于有個(gè)垃圾回收機(jī)制,Java中的對(duì)象不再有"作用域"的概念,只有對(duì)象的引用才有"作用域"。垃圾回收可以有效的防止內(nèi)存泄露,有效的使用可以使用的內(nèi)存。垃圾回收器通常是作為一個(gè)單獨(dú)的低級(jí)別的線程運(yùn)行,不可預(yù)知的情況下對(duì)內(nèi)存堆中已經(jīng)死亡的或者長(zhǎng)時(shí)間沒(méi)有使用的對(duì)象進(jìn)行清楚和回收,程序員不能實(shí)時(shí)的調(diào)用垃圾回收器對(duì)某個(gè)對(duì)象或所有對(duì)象進(jìn)行垃圾回收?;厥諜C(jī)制有分代復(fù)制垃圾回收和標(biāo)記垃圾回收,增量垃圾回收。
70、垃圾回收器的基本原理是什么?垃圾回收器可以馬上回收內(nèi)存嗎?有什么辦法主動(dòng)通知虛擬機(jī)進(jìn)行垃圾回收?
對(duì)于GC來(lái)說(shuō),當(dāng)程序員創(chuàng)建對(duì)象時(shí),GC就開(kāi)始監(jiān)控這個(gè)對(duì)象的地址、大小以及使用情況。通常,GC采用有向圖的方式記錄和管理堆(heap)中的所有對(duì)象。通過(guò)這種方式確定哪些對(duì)象是"可達(dá)的",哪些對(duì)象是"不可達(dá)的"。當(dāng)GC確定一些對(duì)象為"不可達(dá)"時(shí),GC就有責(zé)任回收這些內(nèi)存空間。可以。程序員可以手動(dòng)執(zhí)行System.gc(),通知GC運(yùn)行,但是Java語(yǔ)言規(guī)范并不保證GC一定會(huì)執(zhí)行。
71、什么時(shí)候用assert。
assertion(斷言)在軟件開(kāi)發(fā)中是一種常用的調(diào)試方式,很多開(kāi)發(fā)語(yǔ)言中都支持這種機(jī)制。在實(shí)現(xiàn)中,assertion就是在程序中的一條語(yǔ)句,它對(duì)一個(gè)boolean表達(dá)式進(jìn)行檢查,一個(gè)正確程序必須保證這個(gè)boolean表達(dá)式的值為true;如果該值為false,說(shuō)明程序已經(jīng)處于不正確的狀態(tài)下,assert將給出警告或退出。一般來(lái)說(shuō),assertion用于保證程序最基本、關(guān)鍵的正確性。assertion檢查通常在開(kāi)發(fā)和測(cè)試時(shí)開(kāi)啟。為了提高性能,在軟件發(fā)布后,assertion檢查通常是關(guān)閉的。
package com.huawei.interview;
public class AssertTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int i = 0;
for(i=0;i<5;i++)
{
System.out.println(i);
}
//假設(shè)程序不小心多了一句--i;
--i;
assert i==5;
}
}
72、java中會(huì)存在內(nèi)存泄漏嗎,請(qǐng)簡(jiǎn)單描述。
所謂內(nèi)存泄露就是指一個(gè)不再被程序使用的對(duì)象或變量一直被占據(jù)在內(nèi)存中。java中有垃圾回收機(jī)制,它可以保證一對(duì)象不再被引用的時(shí)候,即對(duì)象編程了孤兒的時(shí)候,對(duì)象將自動(dòng)被垃圾回收器從內(nèi)存中清除掉。由于Java 使用有向圖的方式進(jìn)行垃圾回收管理,可以消除引用循環(huán)的問(wèn)題,例如有兩個(gè)對(duì)象,相互引用,只要它們和根進(jìn)程不可達(dá)的,那么GC也是可以回收它們的,例如下面的代碼可以看到這種情況的內(nèi)存回收:
package com.huawei.interview;
import java.io.IOException;
public class GarbageTest {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
try {
gcTest();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("has exited gcTest!");
System.in.read();
System.in.read();
System.out.println("out begin gc!");
for(int i=0;i<100;i++)
{
System.gc();
System.in.read();
System.in.read();
}
}
private static void gcTest() throws IOException {
System.in.read();
System.in.read();
Person p1 = new Person();
System.in.read();
System.in.read();
Person p2 = new Person();
p1.setMate(p2);
p2.setMate(p1);
System.out.println("before exit gctest!");
System.in.read();
System.in.read();
System.gc();
System.out.println("exit gctest!");
}
private static class Person
{
byte[] data = new byte[20000000];
Person mate = null;
public void setMate(Person other)
{
mate = other;
}
}
}
java中的內(nèi)存泄露的情況:長(zhǎng)生命周期的對(duì)象持有短生命周期對(duì)象的引用就很可能發(fā)生內(nèi)存泄露,盡管短生命周期對(duì)象已經(jīng)不再需要,但是因?yàn)殚L(zhǎng)生命周期對(duì)象持有它的引用而導(dǎo)致不能被回收,這就是java中內(nèi)存泄露的發(fā)生場(chǎng)景,通俗地說(shuō),就是程序員可能創(chuàng)建了一個(gè)對(duì)象,以后一直不再使用這個(gè)對(duì)象,這個(gè)對(duì)象卻一直被引用,即這個(gè)對(duì)象無(wú)用但是卻無(wú)法被垃圾回收器回收的,這就是java中可能出現(xiàn)內(nèi)存泄露的情況,例如,緩存系統(tǒng),我們加載了一個(gè)對(duì)象放在緩存中(例如放在一個(gè)全局map對(duì)象中),然后一直不再使用它,這個(gè)對(duì)象一直被緩存引用,但卻不再被使用。
檢查java中的內(nèi)存泄露,一定要讓程序?qū)⒏鞣N分支情況都完整執(zhí)行到程序結(jié)束,然后看某個(gè)對(duì)象是否被使用過(guò),如果沒(méi)有,則才能判定這個(gè)對(duì)象屬于內(nèi)存泄露。
下面內(nèi)容來(lái)自于網(wǎng)上(主要特點(diǎn)就是清空堆棧中的某個(gè)元素,并不是徹底把它從數(shù)組中拿掉,而是把存儲(chǔ)的總數(shù)減少,本人寫(xiě)得可以比這個(gè)好,在拿掉某個(gè)元素時(shí),順便也讓它從數(shù)組中消失,將那個(gè)元素所在的位置的值設(shè)置為null即可):
我實(shí)在想不到比那個(gè)堆棧更經(jīng)典的例子了,以致于我還要引用別人的例子,下面的例子不是我想到的,是書(shū)上看到的,當(dāng)然如果沒(méi)有在書(shū)上看到,可能過(guò)一段時(shí)間我自己也想的到,可是那時(shí)我說(shuō)是我自己想到的也沒(méi)有人相信的。
public class Stack {
private Object[] elements=new Object[10];
private int size = 0;
public void push(Object e){
ensureCapacity();
elements[size++] = e;
}
public Object pop(){
if( size == 0)
throw new EmptyStackException();
return elements[--size];
}
private void ensureCapacity(){
if(elements.length == size){
Object[] oldElements = elements;
elements = new Object[2 * elements.length+1];
System.arraycopy(oldElements,0, elements, 0, size);
}
}
}
上面的原理應(yīng)該很簡(jiǎn)單,假如堆棧加了10個(gè)元素,然后全部彈出來(lái),雖然堆棧是空的,沒(méi)有我們要的東西,但是這是個(gè)對(duì)象是無(wú)法回收的,這個(gè)才符合了內(nèi)存泄露的兩個(gè)條件:無(wú)用,無(wú)法回收。
但是就是存在這樣的東西也不一定會(huì)導(dǎo)致什么樣的后果,如果這個(gè)堆棧用的比較少,也就浪費(fèi)了幾個(gè)K內(nèi)存而已,反正我們的內(nèi)存都上G了,哪里會(huì)有什么影響,再說(shuō)這個(gè)東西很快就會(huì)被回收的,有什么關(guān)系。下面看兩個(gè)例子。
例子1
public class Bad{
public static Stack s=Stack();
static{
s.push(new Object());
s.pop(); //這里有一個(gè)對(duì)象發(fā)生內(nèi)存泄露
s.push(new Object()); //上面的對(duì)象可以被回收了,等于是自愈了
}
}
因?yàn)槭莝tatic,就一直存在到程序退出,但是我們也可以看到它有自愈功能,就是說(shuō)如果你的Stack最多有100個(gè)對(duì)象,那么最多也就只有100個(gè)對(duì)象無(wú)法被回收其實(shí)這個(gè)應(yīng)該很容易理解,Stack內(nèi)部持有100個(gè)引用,最壞的情況就是他們都是無(wú)用的,因?yàn)槲覀円坏┓判碌倪M(jìn)取,以前的引用自然消失!
73、下面程序的輸出結(jié)果是多少?
import java.util.Date;
public class Test extends Date{
/**
* @param args add by zxx ,Dec 9, 2008
*/
public static void main(String[] args) {
new Test().test();
}
public void test()
{
System.out.println(super.getClass().getName());
}
}
Public class Test1 extends Test{
Public static void main(String[] agrs){
New Test1().test();
}
Public void test(){
System.out.println(getClass().getSuperClass().getName());
}
}
很奇怪,結(jié)果是Test
這屬于腦筋急轉(zhuǎn)彎的題目,在一個(gè)qq群有個(gè)網(wǎng)友正好問(wèn)過(guò)這個(gè)問(wèn)題,我覺(jué)得挺有趣,就研究了一下,沒(méi)想到今天還被你面到了,哈哈。
在test方法中,直接調(diào)用getClass().getName()方法,返回的是Test類名
由于getClass()在Object類中定義成了final,子類不能覆蓋該方法,所以,在
test方法中調(diào)用getClass().getName()方法,其實(shí)就是在調(diào)用從父類繼承的getClass()方法,等效于調(diào)用super.getClass().getName()方法,所以,super.getClass().getName()方法返回的也應(yīng)該是Test。
如果想得到父類的名稱,應(yīng)該用如下代碼:
getClass().getSuperClass().getName();
74、說(shuō)出一些常用的類,包,接口,請(qǐng)各舉5個(gè)
要讓人家感覺(jué)你對(duì)java ee開(kāi)發(fā)很熟,所以,不能僅僅只列core java中的那些東西,要多列你在做ssh項(xiàng)目中涉及的那些東西。就寫(xiě)你最近寫(xiě)的那些程序中涉及的那些類。
常用的類:BufferedReader BufferedWriter FileReader FileWirter String Integer
java.util.Date,System,Class,List,HashMap
常用的包:java.lang java.io java.util java.sql ,javax.servlet,org.apache.strtuts.action,org.hibernate
常用的接口:Remote List Map Document NodeList ,Servlet,HttpServletRequest,HttpServletResponse,Transaction(Hibernate)、Session(Hibernate),HttpSession
2. 特高深的Java問(wèn)題
75、能不能自己寫(xiě)個(gè)類,也叫java.lang.String?
可以,但在應(yīng)用的時(shí)候,需要用自己的類加載器去加載,否則,系統(tǒng)的類加載器永遠(yuǎn)只是去加載jre.jar包中的那個(gè)java.lang.String。由于在tomcat的web應(yīng)用程序中,都是由webapp自己的類加載器先自己加載WEB-INF/classess目錄中的類,然后才委托上級(jí)的類加載器加載,如果我們?cè)趖omcat的web應(yīng)用程序中寫(xiě)一個(gè)java.lang.String,這時(shí)候Servlet程序加載的就是我們自己寫(xiě)的java.lang.String,但是這么干就會(huì)出很多潛在的問(wèn)題,原來(lái)所有用了java.lang.String類的都將出現(xiàn)問(wèn)題。
雖然java提供了endorsed技術(shù),可以覆蓋jdk中的某些類,具體做法是….。但是,能夠被覆蓋的類是有限制范圍,反正不包括java.lang這樣的包中的類。
(下面的例如主要是便于大家學(xué)習(xí)理解只用,不要作為答案的一部分,否則,人家懷疑是題目泄露了)例如,運(yùn)行下面的程序:
package java.lang;
public class String {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("string");
}
}
報(bào)告的錯(cuò)誤如下:
java.lang.NoSuchMethodError: main
Exception in thread "main"
這是因?yàn)榧虞d了jre自帶的java.lang.String,而該類中沒(méi)有main方法。
76. Java代碼查錯(cuò)
1.
abstract class Name {
private String name;
public abstract boolean isStupidName(String name) {}
}
大俠們,這有何錯(cuò)誤?
答案: 錯(cuò)。abstract method必須以分號(hào)結(jié)尾,且不帶花括號(hào)。
2.
public class Something {
void doSomething () {
private String s = "";
int l = s.length();
}
}
有錯(cuò)嗎?
答案: 錯(cuò)。局部變量前不能放置任何訪問(wèn)修飾符 (private,public,和protected)。final可以用來(lái)修飾局部變量
(final如同abstract和strictfp,都是非訪問(wèn)修飾符,strictfp只能修飾class和method而非variable)。
3.
abstract class Something {
private abstract String doSomething ();
}
這好像沒(méi)什么錯(cuò)吧?
答案: 錯(cuò)。abstract的methods不能以private修飾。abstract的methods就是讓子類implement(實(shí)現(xiàn))具體細(xì)節(jié)的,怎么可以用private把a(bǔ)bstract
method封鎖起來(lái)呢? (同理,abstract method前不能加final)。
4.
public class Something {
public int addOne(final int x) {
return ++x;
}
}
這個(gè)比較明顯。
答案: 錯(cuò)。int x被修飾成final,意味著x不能在addOne method中被修改。
5.
public class Something {
public static void main(String[] args) {
Other o = new Other();
new Something().addOne(o);
}
public void addOne(final Other o) {
o.i++;
}
}
class Other {
public int i;
}
和上面的很相似,都是關(guān)于final的問(wèn)題,這有錯(cuò)嗎?
答案: 正確。在addOne method中,參數(shù)o被修飾成final。如果在addOne method里我們修改了o的reference
(比如: o = new Other();),那么如同上例這題也是錯(cuò)的。但這里修改的是o的member vairable
(成員變量),而o的reference并沒(méi)有改變。
6.
class Something {
int i;
public void doSomething() {
System.out.println("i = " + i);
}
}
有什么錯(cuò)呢? 看不出來(lái)啊。
答案: 正確。輸出的是"i = 0"。int i屬於instant variable (實(shí)例變量,或叫成員變量)。instant variable有default value。int的default value是0。
7.
class Something {
final int i;
public void doSomething() {
System.out.println("i = " + i);
}
}
和上面一題只有一個(gè)地方不同,就是多了一個(gè)final。這難道就錯(cuò)了嗎?
答案: 錯(cuò)。final int i是個(gè)final的instant variable (實(shí)例變量,或叫成員變量)。final的instant variable沒(méi)有default value,必須在constructor (構(gòu)造器)結(jié)束之前被賦予一個(gè)明確的值??梢孕薷臑?final int i = 0;"。
8.
public class Something {
public static void main(String[] args) {
Something s = new Something();
System.out.println("s.doSomething() returns " + doSomething());
}
public String doSomething() {
return "Do something ...";
}
}
看上去很完美。
答案: 錯(cuò)??瓷先ピ趍ain里call doSomething沒(méi)有什么問(wèn)題,畢竟兩個(gè)methods都在同一個(gè)class里。但仔細(xì)看,main是static的。static method不能直接call non-static methods。可改成"System.out.println("s.doSomething() returns " + s.doSomething());"。同理,static method不能訪問(wèn)non-static instant variable。
9.
此處,Something類的文件名叫OtherThing.java
class Something {
private static void main(String[] something_to_do) {
System.out.println("Do something ...");
}
}
這個(gè)好像很明顯。
答案: 正確。從來(lái)沒(méi)有人說(shuō)過(guò)Java的Class名字必須和其文件名相同。但public class的名字必須和文件名相同。
10.
interface A{
int x = 0;
}
class B{
int x =1;
}
class C extends B implements A {
public void pX(){
System.out.println(x);
}
public static void main(String[] args) {
new C().pX();
}
}
答案:錯(cuò)誤。在編譯時(shí)會(huì)發(fā)生錯(cuò)誤(錯(cuò)誤描述不同的JVM有不同的信息,意思就是未明確的x調(diào)用,兩個(gè)x都匹配(就象在同時(shí)import java.util和java.sql兩個(gè)包時(shí)直接聲明Date一樣)。對(duì)于父類的變量,可以用super.x來(lái)明確,而接口的屬性默認(rèn)隱含為 public static final.所以可以通過(guò)A.x來(lái)明確。
11.
interface Playable {
void play();
}
interface Bounceable {
void play();
}
interface Rollable extends Playable, Bounceable {
Ball ball = new Ball("PingPang");
}
class Ball implements Rollable {
private String name;
public String getName() {
return name;
}
public Ball(String name) {
this.name = name;
}
public void play() {
ball = new Ball("Football");
System.out.println(ball.getName());
}
}
這個(gè)錯(cuò)誤不容易發(fā)現(xiàn)。
答案: 錯(cuò)。"interface Rollable extends Playable, Bounceable"沒(méi)有問(wèn)題。interface可繼承多個(gè)interfaces,所以這里沒(méi)錯(cuò)。問(wèn)題出在interface Rollable里的"Ball ball = new Ball("PingPang");"。任何在interface里聲明的interface variable (接口變量,也可稱成員變量),默認(rèn)為public static final。也就是說(shuō)"Ball ball = new Ball("PingPang");"實(shí)際上是"public static final Ball ball = new Ball("PingPang");"。在Ball類的Play()方法中,"ball = new Ball("Football");"改變了ball的reference,而這里的ball來(lái)自Rollable interface,Rollable interface里的ball是public static final的,final的object是不能被改變r(jià)eference的。因此編譯器將在"ball = new Ball("Football");"這里顯示有錯(cuò)。
2. 算法與編程
77、說(shuō)明生活中遇到的二叉樹(shù),用java實(shí)現(xiàn)二叉樹(shù)
我有很多個(gè)(假設(shè)10萬(wàn)個(gè))數(shù)據(jù)要保存起來(lái),以后還需要從保存的這些數(shù)據(jù)中檢索是否存在某個(gè)數(shù)據(jù),(我想說(shuō)出二叉樹(shù)的好處,該怎么說(shuō)呢?那就是說(shuō)別人的缺點(diǎn)),假如存在數(shù)組中,那么,碰巧要找的數(shù)字位于99999那個(gè)地方,那查找的速度將很慢,因?yàn)橐獜牡?個(gè)依次往后取,取出來(lái)后進(jìn)行比較。平衡二叉樹(shù)(構(gòu)建平衡二叉樹(shù)需要先排序,我們這里就不作考慮了)可以很好地解決這個(gè)問(wèn)題,但二叉樹(shù)的遍歷(前序,中序,后序)效率要比數(shù)組低很多,原理如下圖:
代碼如下:
package com.huawei.interview;
public class Node {
public int value;
public Node left;
public Node right;
public void store(int value)
{
if(value<this.value)
{
if(left == null)
{
left = new Node();
left.value=value;
}
else
{
left.store(value);
}
}
else if(value>this.value)
{
if(right == null)
{
right = new Node();
right.value=value;
}
else
{
right.store(value);
}
}
}
public boolean find(int value)
{
System.out.println("happen " + this.value);
if(value == this.value)
{
return true;
}
else if(value>this.value)
{
if(right == null) return false;
return right.find(value);
}else
{
if(left == null) return false;
return left.find(value);
}
}
public void preList()
{
System.out.print(this.value + ",");
if(left!=null) left.preList();
if(right!=null) right.preList();
}
public void middleList()
{
if(left!=null) left.preList();
System.out.print(this.value + ",");
if(right!=null) right.preList();
}
public void afterList()
{
if(left!=null) left.preList();
if(right!=null) right.preList();
System.out.print(this.value + ",");
}
public static void main(String [] args)
{
int [] data = new int[20];
for(int i=0;i<data.length;i++)
{
data[i] = (int)(Math.random()*100) + 1;
System.out.print(data[i] + ",");
}
System.out.println();
Node root = new Node();
root.value = data[0];
for(int i=1;i<data.length;i++)
{
root.store(data[i]);
}
root.find(data[19]);
root.preList();
System.out.println();
root.middleList();
System.out.println();
root.afterList();
}
}
78、從類似如下的文本文件中讀取出所有的姓名,并打印出重復(fù)的姓名和重復(fù)的次數(shù),并按重復(fù)次數(shù)排序:
1,張三,28
2,李四,35
3,張三,28
4,王五,35
5,張三,28
6,李四,35
7,趙六,28
8,田七,35
程序代碼如下(答題要博得用人單位的喜歡,包名用該公司,面試前就提前查好該公司的網(wǎng)址,如果查不到,現(xiàn)場(chǎng)問(wèn)也是可以的。還要加上實(shí)現(xiàn)思路的注釋):
package com.huawei.interview;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;
public class GetNameTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//InputStream ips = GetNameTest.class.getResourceAsStream("/com/huawei/interview/info.txt");
//用上一行注釋的代碼和下一行的代碼都可以,因?yàn)閕nfo.txt與GetNameTest類在同一包下面,所以,可以用下面的相對(duì)路徑形式
Map results = new HashMap();
InputStream ips = GetNameTest.class.getResourceAsStream("info.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(ips));
String line = null;
try {
while((line=in.readLine())!=null)
{
dealLine(line,results);
}
sortResults(results);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static class User
{
public String name;
public Integer value;
public User(String name,Integer value)
{
this.name = name;
this.value = value;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
//下面的代碼沒(méi)有執(zhí)行,說(shuō)明往treeset中增加數(shù)據(jù)時(shí),不會(huì)使用到equals方法。
boolean result = super.equals(obj);
System.out.println(result);
return result;
}
}
private static void sortResults(Map results) {
// TODO Auto-generated method stub
TreeSet sortedResults = new TreeSet(
new Comparator(){
public int compare(Object o1, Object o2) {
// TODO Auto-generated method stub
User user1 = (User)o1;
User user2 = (User)o2;
/*如果compareTo返回結(jié)果0,則認(rèn)為兩個(gè)對(duì)象相等,新的對(duì)象不會(huì)增加到集合中去
* 所以,不能直接用下面的代碼,否則,那些個(gè)數(shù)相同的其他姓名就打印不出來(lái)。
* */
//return user1.value-user2.value;
//return user1.value<user2.value?-1:user1.value==user2.value?0:1;
if(user1.value<user2.value)
{
return -1;
}else if(user1.value>user2.value)
{
return 1;
}else
{
return user1.name.compareTo(user2.name);
}
}
}
);
Iterator iterator = results.keySet().iterator();
while(iterator.hasNext())
{
String name = (String)iterator.next();
Integer value = (Integer)results.get(name);
if(value > 1)
{
sortedResults.add(new User(name,value));
}
}
printResults(sortedResults);
}
private static void printResults(TreeSet sortedResults)
{
Iterator iterator = sortedResults.iterator();
while(iterator.hasNext())
{
User user = (User)iterator.next();
System.out.println(user.name + ":" + user.value);
}
}
public static void dealLine(String line,Map map)
{
if(!"".equals(line.trim()))
{
String [] results = line.split(",");
if(results.length == 3)
{
String name = results[1];
Integer value = (Integer)map.get(name);
if(value == null) value = 0;
map.put(name,value + 1);
}
}
}
}
79、寫(xiě)一個(gè)Singleton出來(lái)。
Singleton模式主要作用是保證在Java應(yīng)用程序中,一個(gè)類Class只有一個(gè)實(shí)例存在。
一般Singleton模式通常有幾種種形式:
第一種形式: 定義一個(gè)類,它的構(gòu)造函數(shù)為private的,它有一個(gè)static的private的該類變量,在類初始化時(shí)實(shí)例話,通過(guò)一個(gè)public的getInstance方法獲取對(duì)它的引用,繼而調(diào)用其中的方法。
public class Singleton {
private Singleton(){}
//在自己內(nèi)部定義自己一個(gè)實(shí)例,是不是很奇怪?
//注意這是private 只供內(nèi)部調(diào)用
private static Singleton instance = new Singleton();
//這里提供了一個(gè)供外部訪問(wèn)本class的靜態(tài)方法,可以直接訪問(wèn)
public static Singleton getInstance() {
return instance;
}
}
第二種形式:
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//這個(gè)方法比上面有所改進(jìn),不用每次都進(jìn)行生成對(duì)象,只是第一次
//使用時(shí)生成實(shí)例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance;
}
}
其他形式:
定義一個(gè)類,它的構(gòu)造函數(shù)為private的,所有方法為static的。
一般認(rèn)為第一種形式要更加安全些
80、遞歸算法題1
一個(gè)整數(shù),大于0,不用循環(huán)和本地變量,按照n,2n,4n,8n的順序遞增,當(dāng)值大于5000時(shí),把值按照指定順序輸出來(lái)。
例:n=1237
則輸出為:
1237,
2474,
4948,
9896,
9896,
4948,
2474,
1237,
public static void multiply(int n)
{
if(n>5000) return;
System.out.println(n);
multiply(n*2);
System.out.println(n);
}
81、遞歸算法題2
第1個(gè)人10,第2個(gè)比第1個(gè)人大2歲,依次遞推,第8個(gè)人多大?
package cn.itcast;
import java.util.Date;
public class A1 {
public static void main(String [] args)
{
System.out.println(computeAge(8));
}
public static int computeAge(int n)
{
if(n==1) return 10;
return computeAge(n-1) + 2;
}
}
public static void toBinary(int n,StringBuffer result)
{
if(n/2 != 0)
toBinary(n/2,result);
result.append(n%2);
}
82、排序都有哪幾種方法?請(qǐng)列舉。用JAVA實(shí)現(xiàn)一個(gè)快速排序。
本人只研究過(guò)冒泡排序、選擇排序和快速排序,下面是快速排序的代碼:
public class QuickSort {
/**
* 快速排序
* @param strDate
* @param left
* @param right
*/
public void quickSort(String[] strDate,int left,int right){
String middle,tempDate;
int i,j;
i=left;
j=right;
middle=strDate[(i+j)/2];
do{
while(strDate[i].compareTo(middle)<0&& i<right)
i++; //找出左邊比中間值大的數(shù)
while(strDate[j].compareTo(middle)>0&& j>left)
j--; //找出右邊比中間值小的數(shù)
if(i<=j){ //將左邊大的數(shù)和右邊小的數(shù)進(jìn)行替換
tempDate=strDate[i];
strDate[i]=strDate[j];
strDate[j]=tempDate;
i++;
j--;
}
}while(i<=j); //當(dāng)兩者交錯(cuò)時(shí)停止
if(i<right){
quickSort(strDate,i,right);//從
}
if(j>left){
quickSort(strDate,left,j);
}
}
/**
* @param args
*/
public static void main(String[] args){
String[] strVoid=new String[]{"11","66","22","0","55","22","0","32"};
QuickSort sort=new QuickSort();
sort.quickSort(strVoid,0,strVoid.length-1);
for(int i=0;i<strVoid.length;i++){
System.out.println(strVoid[i]+" ");
}
}
}
83、有數(shù)組a[n],用java代碼將數(shù)組元素順序顛倒
package cn.itcast.lecture2;
import java.util.Arrays;
import java.util.Collections;
public class ReverseTest {
public static void main(String [] args)
{
//產(chǎn)生若干0到1000的隨機(jī)數(shù),作為數(shù)組的初始值
int data[] = new int[]{
(int)(Math.random() * 1000),
(int)(Math.random() * 1000),
(int)(Math.random() * 1000),
(int)(Math.random() * 1000),
(int)(Math.random() * 1000),
(int)(Math.random() * 1000),
(int)(Math.random() * 100),
};
System.out.println(Math.random());
System.out.print("交換前的數(shù)據(jù):");
System.out.println(
Arrays.toString(data));
reverse(data);
System.out.print("交換后的數(shù)據(jù):");
System.out.println(Arrays.toString(data));
}
//方法執(zhí)行完后,參數(shù)data中的數(shù)據(jù)順序即被顛倒
//實(shí)現(xiàn)思路是第1個(gè)和第n個(gè)交換,第2個(gè)和第n-1個(gè)交換,依次類推...
public static void reverse(int[] data)
{
int len = data.length;
for(int i=0;i<len/2;i++)
{
int temp = data[i];
data[i] = data[len-1-i];
data[len-1-i] = temp;
}
}
}
84.金額轉(zhuǎn)換,阿拉伯?dāng)?shù)字的金額轉(zhuǎn)換成中國(guó)傳統(tǒng)的形式如:(¥1011)->(一千零一拾一元整)輸出。
public class RenMingBi {
/**
* @param args add by zxx ,Nov 29, 2008
*/
private static final char[] data = new char[]{
'零','壹','貳','叁','肆','伍','陸','柒','捌','玖'
};
private static final char[] units = new char[]{
'元','拾','佰','仟','萬(wàn)','拾','佰','仟','億'
};
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(
convert(135689123));
}
public static String convert(int money)
{
StringBuffer sbf = new StringBuffer();
int unit = 0;
while(money!=0)
{
sbf.insert(0,units[unit++]);
int number = money%10;
sbf.insert(0, data[number]);
money /= 10;
}
return sbf.toString();
}
}
2. html&JavaScript部分
85. 判斷第二個(gè)日期比第一個(gè)日期大
如何用腳本判斷用戶輸入的的字符串是下面的時(shí)間格式2004-11-21 必須要保證用戶的輸入是此格式,并且是時(shí)間,比如說(shuō)月份不大于12等等,另外我需要用戶輸入兩個(gè),并且后一個(gè)要比前一個(gè)晚,只允許用JAVASCRIPT,請(qǐng)?jiān)敿?xì)幫助作答,,
//這里可用正則表達(dá)式判斷提前判斷一下格式,然后按下提取各時(shí)間字段內(nèi)容
<input type="text" id="d1"/>
<input type="text" id="d2" οnblur="compare()"/>
<script>
function compare()
{
var d1 = document.getElementById("d1").value;
var d2 = document.getElementById("d2").value;
arr1 = d1.split("-");
arr2 = d2.split("-");
date1 = new Date(arr1[0],arr1[1],arr1[2]);
date2 = new Date(arr2[0],arr2[1],arr2[2]);
if(date2.getTime()<date1.getTime())
{
alert("不能比第一個(gè)日期小");
return false;
}
}
</script>
86. 用table顯示n條記錄,每3行換一次顏色,即1,2,3用紅色字體,4,5,6用綠色字體,7,8,9用紅顏色字體。
87、HTML 的 form 提交之前如何驗(yàn)證數(shù)值不為空? 為空的話提示用戶并終止提交?
88、請(qǐng)寫(xiě)出用于校驗(yàn)HTML文本框中輸入的內(nèi)容全部為數(shù)字的javascript代碼
var re=/^\d{1,8}$|\.\d{1,2}$/;
var str=document.form1.all(i).value;
var r=str.match(re);
if (r==null)
{
sign=-4;
break;
}
else{
document.form1.all(i).value=parseFloat(str);
}
3. Java web部分
89、HTTP請(qǐng)求的GET與POST方式的區(qū)別
答:servlet有良好的生存期的定義,包括加載和實(shí)例化、初始化、處理請(qǐng)求以及服務(wù)結(jié)束。這個(gè)生存期由javax.servlet.Servlet接口的init,service和destroy方法表達(dá)。
90、解釋一下什么是servlet;
答:servlet有良好的生存期的定義,包括加載和實(shí)例化、初始化、處理請(qǐng)求以及服務(wù)結(jié)束。這個(gè)生存期由javax.servlet.Servlet接口的init,service和destroy方法表達(dá)。
91、說(shuō)一說(shuō)Servlet的生命周期?
答:servlet有良好的生存期的定義,包括加載和實(shí)例化、初始化、處理請(qǐng)求以及服務(wù)結(jié)束。這個(gè)生存期由javax.servlet.Servlet接口的init,service和destroy方法表達(dá)。
Servlet被服務(wù)器實(shí)例化后,容器運(yùn)行其init方法,請(qǐng)求到達(dá)時(shí)運(yùn)行其service方法,service方法自動(dòng)派遣運(yùn)行與請(qǐng)求對(duì)應(yīng)的doXXX方法(doGet,doPost)等,當(dāng)服務(wù)器決定將實(shí)例銷(xiāo)毀的時(shí)候調(diào)用其destroy方法。
web容器加載servlet,生命周期開(kāi)始。通過(guò)調(diào)用servlet的init()方法進(jìn)行servlet的初始化。通過(guò)調(diào)用service()方法實(shí)現(xiàn),根據(jù)請(qǐng)求的不同調(diào)用不同的do***()方法。結(jié)束服務(wù),web容器調(diào)用servlet的destroy()方法。
92、Servlet的基本架構(gòu)
public class ServletName extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
}
}
93、SERVLET API中forward() 與redirect()的區(qū)別?
答:前者僅是容器中控制權(quán)的轉(zhuǎn)向,在客戶端瀏覽器地址欄中不會(huì)顯示出轉(zhuǎn)向后的地址;后者則是完全的跳轉(zhuǎn),瀏覽器將會(huì)得到跳轉(zhuǎn)的地址,并重新發(fā)送請(qǐng)求鏈接。這樣,從瀏覽器的地址欄中可以看到跳轉(zhuǎn)后的鏈接地址。所以,前者更加高效,在前者可以滿足需要時(shí),盡量使用forward()方法,并且,這樣也有助于隱藏實(shí)際的鏈接。在有些情況下,比如,需要跳轉(zhuǎn)到一個(gè)其它服務(wù)器上的資源,則必須使用
sendRedirect()方法。
94、什么情況下調(diào)用doGet()和doPost()?
Jsp頁(yè)面中的FORM標(biāo)簽里的method屬性為get時(shí)調(diào)用doGet(),為post時(shí)調(diào)用doPost()。
95、Request對(duì)象的主要方法:
setAttribute(String name,Object):設(shè)置名字為name的request的參數(shù)值
getAttribute(String name):返回由name指定的屬性值
getAttributeNames():返回request對(duì)象所有屬性的名字集合,結(jié)果是一個(gè)枚舉的實(shí)例
getCookies():返回客戶端的所有Cookie對(duì)象,結(jié)果是一個(gè)Cookie數(shù)組
getCharacterEncoding():返回請(qǐng)求中的字符編碼方式
getContentLength():返回請(qǐng)求的Body的長(zhǎng)度
getHeader(String name):獲得HTTP協(xié)議定義的文件頭信息
getHeaders(String name):返回指定名字的request Header的所有值,結(jié)果是一個(gè)枚舉的實(shí)例
getHeaderNames():返回所以request Header的名字,結(jié)果是一個(gè)枚舉的實(shí)例
getInputStream():返回請(qǐng)求的輸入流,用于獲得請(qǐng)求中的數(shù)據(jù)
getMethod():獲得客戶端向服務(wù)器端傳送數(shù)據(jù)的方法
getParameter(String name):獲得客戶端傳送給服務(wù)器端的有name指定的參數(shù)值
getParameterNames():獲得客戶端傳送給服務(wù)器端的所有參數(shù)的名字,結(jié)果是一個(gè)枚舉的實(shí)例
getParametervalues(String name):獲得有name指定的參數(shù)的所有值
getProtocol():獲取客戶端向服務(wù)器端傳送數(shù)據(jù)所依據(jù)的協(xié)議名稱
getQueryString():獲得查詢字符串
getRequestURI():獲取發(fā)出請(qǐng)求字符串的客戶端地址
getRemoteAddr():獲取客戶端的IP地址
getRemoteHost():獲取客戶端的名字
getSession([Boolean create]):返回和請(qǐng)求相關(guān)Session
getServerName():獲取服務(wù)器的名字
getServletPath():獲取客戶端所請(qǐng)求的腳本文件的路徑
getServerPort():獲取服務(wù)器的端口號(hào)
removeAttribute(String name):刪除請(qǐng)求中的一個(gè)屬性
96、forward 和redirect的區(qū)別
forward是服務(wù)器請(qǐng)求資源,服務(wù)器直接訪問(wèn)目標(biāo)地址的URL,把那個(gè)URL的響應(yīng)內(nèi)容讀取過(guò)來(lái),然后把這些內(nèi)容再發(fā)給瀏覽器,瀏覽器根本不知道服務(wù)器發(fā)送的內(nèi)容是從哪兒來(lái)的,所以它的地址欄中還是原來(lái)的地址。
redirect就是服務(wù)端根據(jù)邏輯,發(fā)送一個(gè)狀態(tài)碼,告訴瀏覽器重新去請(qǐng)求那個(gè)地址,一般來(lái)說(shuō)瀏覽器會(huì)用剛才請(qǐng)求的所有參數(shù)重新請(qǐng)求,所以session,request參數(shù)都可以獲取。
97、request.getAttribute() 和 request.getParameter() 有何區(qū)別?
98. jsp有哪些內(nèi)置對(duì)象?作用分別是什么? 分別有什么方法?
答:JSP共有以下9個(gè)內(nèi)置的對(duì)象:
request 用戶端請(qǐng)求,此請(qǐng)求會(huì)包含來(lái)自GET/POST請(qǐng)求的參數(shù)
response 網(wǎng)頁(yè)傳回用戶端的回應(yīng)
pageContext 網(wǎng)頁(yè)的屬性是在這里管理
session 與請(qǐng)求有關(guān)的會(huì)話期
application servlet 正在執(zhí)行的內(nèi)容
out 用來(lái)傳送回應(yīng)的輸出
config servlet的構(gòu)架部件
page JSP網(wǎng)頁(yè)本身
exception 針對(duì)錯(cuò)誤網(wǎng)頁(yè),未捕捉的例外
request表示HttpServletRequest對(duì)象。它包含了有關(guān)瀏覽器請(qǐng)求的信息,并且提供了幾個(gè)用于獲取cookie, header, 和session數(shù)據(jù)的有用的方法。
response表示HttpServletResponse對(duì)象,并提供了幾個(gè)用于設(shè)置送回 瀏覽器的響應(yīng)的方法(如cookies,頭信息等)
out對(duì)象是javax.jsp.JspWriter的一個(gè)實(shí)例,并提供了幾個(gè)方法使你能用于向?yàn)g覽器回送輸出結(jié)果。
pageContext表示一個(gè)javax.servlet.jsp.PageContext對(duì)象。它是用于方便存取各種范圍的名字空間、servlet相關(guān)的對(duì)象的API,并且包裝了通用的servlet相關(guān)功能的方法。
session表示一個(gè)請(qǐng)求的javax.servlet.http.HttpSession對(duì)象。Session可以存貯用戶的狀態(tài)信息
applicaton 表示一個(gè)javax.servle.ServletContext對(duì)象。這有助于查找有關(guān)servlet引擎和servlet環(huán)境的信息
config表示一個(gè)javax.servlet.ServletConfig對(duì)象。該對(duì)象用于存取servlet實(shí)例的初始化參數(shù)。
page表示從該頁(yè)面產(chǎn)生的一個(gè)servlet實(shí)例
99. jsp有哪些動(dòng)作?作用分別是什么?
(這個(gè)問(wèn)題似乎不重要,不明白為何有此題)
答:JSP共有以下6種基本動(dòng)作
jsp:include:在頁(yè)面被請(qǐng)求的時(shí)候引入一個(gè)文件。
jsp:useBean:尋找或者實(shí)例化一個(gè)JavaBean。
jsp:setProperty:設(shè)置JavaBean的屬性。
jsp:getProperty:輸出某個(gè)JavaBean的屬性。
jsp:forward:把請(qǐng)求轉(zhuǎn)到一個(gè)新的頁(yè)面。
jsp:plugin:根據(jù)瀏覽器類型為Java插件生成OBJECT或EMBED標(biāo)記
100、JSP的常用指令
isErrorPage(是否能使用Exception對(duì)象),isELIgnored(是否忽略表達(dá)式)
101. JSP中動(dòng)態(tài)INCLUDE與靜態(tài)INCLUDE的區(qū)別?
答:動(dòng)態(tài)INCLUDE用jsp:include動(dòng)作實(shí)現(xiàn)
<jsp:include page=included.jsp flush=true />它總是會(huì)檢查所含文件中的變化,適合用于包含動(dòng)態(tài)頁(yè)面,并且可以帶參數(shù) 靜態(tài)INCLUDE用include偽碼實(shí)現(xiàn),定不會(huì)檢查所含文件的變化,適用于包含靜態(tài)頁(yè)面 <%@ include file=included.htm %>
102、兩種跳轉(zhuǎn)方式分別是什么?有什么區(qū)別?
(下面的回答嚴(yán)重錯(cuò)誤,應(yīng)該是想問(wèn)forward和sendRedirect 的區(qū)別,畢竟出題的人不是專業(yè)搞文字藝術(shù)的人,可能表達(dá)能力并不見(jiàn)得很強(qiáng),用詞不一定精準(zhǔn),加之其自身的技術(shù)面也可能存在一些問(wèn)題,不一定真正將他的意思表達(dá)清楚了,嚴(yán)格意思上來(lái)講,一些題目可能根本就無(wú)人能答,所以,答題時(shí)要掌握主動(dòng),只要把自己知道的表達(dá)清楚就夠了,而不要去推敲原始題目的具體含義是什么,不要一味想著是在答題)
答:有兩種,分別為:
<jsp:include page=included.jsp flush=true>
<jsp:forward page= nextpage.jsp/>
前者頁(yè)面不會(huì)轉(zhuǎn)向include所指的頁(yè)面,只是顯示該頁(yè)的結(jié)果,主頁(yè)面還是原來(lái)的頁(yè)面。執(zhí)行完后還會(huì)回來(lái),相當(dāng)于函數(shù)調(diào)用。并且可以帶參數(shù).后者完全轉(zhuǎn)向新頁(yè)面,不會(huì)再回來(lái)。相當(dāng)于go to 語(yǔ)句。
103、頁(yè)面間對(duì)象傳遞的方法
request,session,application,cookie等
104、JSP和Servlet有哪些相同點(diǎn)和不同點(diǎn),他們之間的聯(lián)系是什么?
JSP是Servlet技術(shù)的擴(kuò)展,本質(zhì)上是Servlet的簡(jiǎn)易方式,更強(qiáng)調(diào)應(yīng)用的外表表達(dá)。JSP編譯后是"類servlet"。Servlet和JSP最主要的不同點(diǎn)在于,Servlet的應(yīng)用邏輯是在Java文件中,并且完全從表示層中的HTML里分離開(kāi)來(lái)。而JSP的情況是Java和HTML可以組合成一個(gè)擴(kuò)展名為.jsp的文件。JSP側(cè)重于視圖,Servlet主要用于控制邏輯。
105、MVC的各個(gè)部分都有那些技術(shù)來(lái)實(shí)現(xiàn)?如何實(shí)現(xiàn)?
答:MVC是Model-View-Controller的簡(jiǎn)寫(xiě)。Model 代表的是應(yīng)用的業(yè)務(wù)邏輯(通過(guò)JavaBean,EJB組件實(shí)現(xiàn)), View 是應(yīng)用的表示面(由JSP頁(yè)面產(chǎn)生),Controller 是提供應(yīng)用的處理過(guò)程控制(一般是一個(gè)Servlet),通過(guò)這種設(shè)計(jì)模型把應(yīng)用邏輯,處理過(guò)程和顯示邏輯分成不同的組件實(shí)現(xiàn)。這些組件可以進(jìn)行交互和重用。
106、我們?cè)趙eb應(yīng)用開(kāi)發(fā)過(guò)程中經(jīng)常遇到輸出某種編碼的字符,如iso8859-1等,如何輸出一個(gè)某種編碼的字符串?
Public String translate (String str) {
String tempStr = "";
try {
tempStr = new String(str.getBytes("ISO-8859-1"), "GBK");
tempStr = tempStr.trim();
}
catch (Exception e) {
System.err.println(e.getMessage());
}
return tempStr;
}
107.現(xiàn)在輸入n個(gè)數(shù)字,以逗號(hào),分開(kāi);然后可選擇升或者降序排序;按提交鍵就在另一頁(yè)面顯示按什么排序,結(jié)果為,提供reset
108. 數(shù)據(jù)庫(kù)部分
109、數(shù)據(jù)庫(kù)三范式是什么?
第一范式:1NF是對(duì)屬性的原子性約束,要求屬性具有原子性,不可再分解
第二范式:2NF是對(duì)記錄的唯一約束,要求記錄有唯一標(biāo)識(shí),即實(shí)體的唯一性
第三范式:3NF是對(duì)字段行的約束,即任何字段不能由其他字段派生出來(lái),要求字段沒(méi)有余,,(是直接相關(guān)而不是間接相關(guān))
110、說(shuō)出一些數(shù)據(jù)庫(kù)優(yōu)化方面的經(jīng)驗(yàn)?
111、union和union all有什么不同?
Union會(huì)自動(dòng)壓縮多個(gè)結(jié)果集合中的重復(fù)結(jié)果,而union all則將所有的結(jié)果全部顯示出來(lái),不管是不是重復(fù), union:對(duì)兩個(gè)結(jié)果集驚醒并集操作,不包括重復(fù)行,同時(shí)進(jìn)行默認(rèn)規(guī)則的排序,union all;對(duì)兩個(gè)結(jié)果集進(jìn)行并集操作包括重復(fù)行,不進(jìn)行排序;
112查出比經(jīng)理薪水還高的員工信息:
Drop table if not exists employees;
create table employees(id int primary key auto_increment,name varchar(50)
,salary int,managerid int references employees(id));
insert into employees values (null,'zxx',10000,null), (null,'lhm',15000,1
),(null,'flx',9000,1),(null,'tg',10000,2),(null,'wzg',10000,3);
Wzg大于flx,lhm大于zxx
select e.* from employees e,employees m where e.managerid=m.id and e.sala
ry>m.salary;
113、oracle關(guān)聯(lián)查詢題目1
數(shù)據(jù)庫(kù)中有3個(gè)表 teacher 表,student表,tea_stu關(guān)系表。
teacher 表 teaID name age
student 表 stuID name age
teacher_student表 teaID stuID
要求用一條sql查詢出這樣的結(jié)果
1.顯示的字段要有老師name, age 每個(gè)老師所帶的學(xué)生人數(shù)
2 只列出老師age為40以下學(xué)生age為12以上的記錄
預(yù)備知識(shí):
1.sql語(yǔ)句是對(duì)每一條記錄依次處理,條件為真則執(zhí)行動(dòng)作(select,insert,delete,update)
2.只要是迪卡爾積,就會(huì)產(chǎn)生“垃圾”信息,所以,只要迪卡爾積了,我們首先就要想到清除“垃圾”信息
實(shí)驗(yàn)準(zhǔn)備:
drop table if exists tea_stu;
drop table if exists teacher;
drop table if exists student;
create table teacher(teaID int primary key,name varchar(50),age int);
create table student(stuID int primary key,name varchar(50),age int);
create table tea_stu(teaID int references teacher(teaID),stuID int references student(stuID));
insert into teacher values(1,'zxx',45), (2,'lhm',25) , (3,'wzg',26) , (4,'tg',27);
insert into student values(1,'wy',11), (2,'dh',25) , (3,'ysq',26) , (4,'mxc',27);
insert into tea_stu values(1,1), (1,2), (1,3);
insert into tea_stu values(2,2), (2,3), (2,4);
insert into tea_stu values(3,3), (3,4), (3,1);
insert into tea_stu values(4,4), (4,1), (4,2) , (4,3);
結(jié)果:2à3,3à2,4à3
解題思路:(真實(shí)面試答題時(shí),也要寫(xiě)出每個(gè)分析步驟,如果紙張不夠,就找別人要)
1要會(huì)統(tǒng)計(jì)分組信息:
select teaid,count(*) from tea_stu group by teaid;
2.要會(huì)篩選大于40的老師
先講給1號(hào)學(xué)生帶課的所有老師的名字,要知道1號(hào)學(xué)生的老師,要從哪個(gè)表獲得?從tea_stu里才可以,從這個(gè)表里獲得的是老師的什么?是老師的teaID,如果要得到老師的名稱,則必須拿著teaID去teacher里找。所以,這兩個(gè)表要進(jìn)行關(guān)聯(lián),關(guān)聯(lián)就引出迪卡爾既的問(wèn)題。假設(shè)我們好獲得teaID為1的老師的名稱,我們要關(guān)聯(lián)的是哪條記錄?是1那一條,但是,迪卡爾既的結(jié)果有幾條啊?4條,顯然,我接著要做的就是把其他垃圾的3條去掉。
select * from tea_stu,teacher where tea_stu.teaID=teacher.teaID;
再接著去掉大于40的老師:
select * from tea_stu,teacher where tea_stu.teaID=teacher.teaID and teacher.age<=40;
3.再對(duì)上面的結(jié)果去掉小于12的學(xué)生
select * from
(select tea_stu.* from tea_stu,teacher where tea_stu.teaID=
teacher.teaID and teacher.age<40) as t,
student
where t.stuid=student.stuid and student.age>12;
4.再對(duì)上面的結(jié)果進(jìn)行統(tǒng)計(jì),顯示的是老師的id和組信息
select t.teaID,count(*) from
(select tea_stu.* from tea_stu,teacher where tea_stu.teaID=
teacher.teaID and teacher.age<40) as t,
student
where t.stuid=student.stuid and student.age>12
group by t.teaID;
5.然后對(duì)上面的東西進(jìn)行改寫(xiě),改寫(xiě)成顯示老師的名字
select teacher.name,t2.c from
(select t.teaID,count(*) c from
(select tea_stu.* from tea_stu,teacher where tea_stu.teaID=
teacher.teaID and teacher.age<40) as t,
student
where t.stuid=student.stuid and student.age>12
group by t.teaID) as t2,
teacher
where teacher.teaID=t2.teaID;
第二種寫(xiě)法:
select teacher.teaID, teacher.name, t1.total from teacher,
(select teaID,count(tea_stu.stuID) total from tea_stu, student
where tea_stu.stuID = student.stuID and student.age>12
group by teaID ) as t1
where teacher.teaID = t1.teaID and teacher.age<40 ;
求出發(fā)帖最多的人:
select authorid,count(*) total from articles
group by authorid
having total=
(select max(total2) from (select count(*) total2 from articles group by authorid) as t);
select t.authorid,max(t.total) from
(select authorid,count(*) total from articles )as t
這條語(yǔ)句不行,因?yàn)閙ax只有一列,不能與其他列混淆。
select authorid,count(*) total from articles
group by authorid having total=max(total)也不行。
114、什么是存儲(chǔ)過(guò)程和如何編寫(xiě)
存儲(chǔ)過(guò)程是一組為了完成特定功能的sql語(yǔ)句集,
create or replace
procedure test
as
begin
過(guò)程
end;
--調(diào)用
begin
test;
end;
115、注冊(cè)Jdbc驅(qū)動(dòng)程序的三種方式
1,Class.forName(“com.oracle.jdbc.Driver”);
2,DriverManger.registerDriver(new com.oracle.jdbc.Driver());
3,System.setProperty(“jdbc.drivers”,”com.oracle.jdbc.Driver”);
116、用JDBC如何調(diào)用存儲(chǔ)過(guò)程
{call過(guò)程名[(?,?,,,,)]}返回結(jié)果參數(shù)的過(guò)程的語(yǔ)法為
{?=call過(guò)程名[(?,?,,,,)]}
不帶參的:{call過(guò)程名}
117、JDBC中的PreparedStatement相比Statement的好處
1,相對(duì)比較安全,可以防止sql注入
2,有裕編譯功能,相同的操作批量數(shù)據(jù)效率較高
118. 寫(xiě)一個(gè)用jdbc連接并訪問(wèn)oracle數(shù)據(jù)的程序代碼
private static final String DRIVER = " com.oracle.jdbc.driver.OracleDriver ";
private static final String URL = "jdbc:oracle:thin:@localhost:1521 =orcl";
private static final String UNAME = "sa";
private static final String PASS = "123";
Class.forName(DRIVER);
conn = DriverManager.getConnection(URL,UNAME,PASS);
119、Class.forName的作用?為什么要用?
Class.forName(“”)返回的是以個(gè)類,任何Class都要裝載虛擬機(jī)上才能運(yùn)行,class.forName();就是裝載類用的,(和NEW不一樣,)
用:比如說(shuō)給你以個(gè)字符串(代表以類的包名和類名),要你把他的類加載到虛擬機(jī)上的時(shí)候就要用到了,
答:調(diào)用該訪問(wèn)返回一個(gè)以字符串指定類名的類的對(duì)象。
120、大數(shù)據(jù)量下的分頁(yè)解決方法。
121、用 JDBC 查詢學(xué)生成績(jī)單, 把主要代碼寫(xiě)出來(lái).
Connection getConnection()
{
private static final String DRIVER = " com.orcl.jdbc.Driver ";
private static final String URL = "jdbc:orcl ://localhost:1433;databasename=test";
private static final String UNAME = "sa";
private static final String PASS = "123";
Class.forName("com.orcl.jdbc.Driver");
return java.sql.DriverManager.getConnention(dbURL,dbUser,dbPwd);
}
public Employee getEmployee() throws SQLException {
STUDENT employee = null;
String sql = "SELECT * FROM STUDENT";
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
employee = null;
while (rs.next()) {
employee = new STUDENT ();
employee.stuid (rs.getInt("ID"));
}
} finally {
try {
if (rs != null)
rs.close();
} finally {
try {
if (ps != null)
ps.close();
} finally {
if (conn != null)
conn.close();
}
}
}
return employee;
}
122、這段代碼有什么不足之處?
try {
Connection conn = ...;
Statement stmt = ...;
ResultSet rs = stmt.executeQuery("select * from table1");
while(rs.next()) {
}
} catch(Exception ex) {
}
需要異常處理
123、說(shuō)出數(shù)據(jù)連接池的工作機(jī)制是什么?
J2EE服務(wù)器啟動(dòng)時(shí)會(huì)建立一定數(shù)量的池連接,并一直維持不少于此數(shù)目的池連接??蛻舳顺绦蛐枰B接時(shí),池驅(qū)動(dòng)程序會(huì)返回一個(gè)未使用的池連接并將其表記為忙。如果當(dāng)前沒(méi)有空閑連接,池驅(qū)動(dòng)程序就新建一定數(shù)量的連接,新建連接的數(shù)量有配置參數(shù)決定。當(dāng)使用的池連接調(diào)用完成后,池驅(qū)動(dòng)程序?qū)⒋诉B接表記為空閑,其他調(diào)用就可以使用這個(gè)連接。
124、為什么要用 ORM? 和 JDBC 有何不一樣?
Orm建立java對(duì)象與數(shù)據(jù)庫(kù)對(duì)象之間的映射關(guān)系,程序員不需要編寫(xiě)復(fù)雜的sql語(yǔ)句,直接操作java對(duì)象即可,從而大大降低了代碼量,也是程序員更加專注于業(yè)務(wù)邏輯的實(shí)現(xiàn),
1. 代碼繁瑣問(wèn)題,用jdbc訪問(wèn)數(shù)據(jù)庫(kù)代碼量大繁瑣,容易出錯(cuò),
2. 數(shù)據(jù)庫(kù)連接問(wèn)題,,關(guān)系數(shù)據(jù)對(duì)象之間,存在各種關(guān)系,,如果程序員用jdbc編程的話,就必須十分小心的處理這些關(guān)系,而這個(gè)過(guò)程是個(gè)很痛苦的過(guò)程,
3. Orm建立java對(duì)象與數(shù)據(jù)庫(kù)對(duì)象關(guān)系映射,也自動(dòng)根據(jù)數(shù)據(jù)庫(kù)對(duì)象之間的關(guān)系創(chuàng)建java對(duì)象的關(guān)系,并且提供了維持這些關(guān)系的完整有效機(jī)制
4. 系統(tǒng)架構(gòu)問(wèn)題,現(xiàn)在的應(yīng)用系統(tǒng)一般由展示層,業(yè)務(wù)層,數(shù)據(jù)訪問(wèn)層,數(shù)據(jù)層,各層次功能劃分非常清楚,jdbc屬于數(shù)據(jù)訪問(wèn)層,使用jdbc編程時(shí)就必須知道后臺(tái)使用的是什么數(shù)據(jù)庫(kù),有哪些表,哪些字段,表與表之間有什么關(guān)系,索引,等等,,使用orm可以完全的屏蔽數(shù)據(jù)庫(kù),給程序員的只有java對(duì)象,程序員只需要根據(jù)業(yè)務(wù)邏輯的需要調(diào)用java對(duì)象,就可以實(shí)現(xiàn)對(duì)后臺(tái)的數(shù)據(jù)庫(kù)操作
5. 性能問(wèn)題,jdbc很多時(shí)候存在效率地下的問(wèn)題,orm框架講根據(jù)具體數(shù)據(jù)庫(kù)操作需要,會(huì)自動(dòng)的延遲向后臺(tái)數(shù)據(jù)庫(kù)發(fā)送sql請(qǐng)求,盡量減少不必要的數(shù)據(jù)操作請(qǐng)求操作,
5. XML部分
125、xml有哪些解析技術(shù)?區(qū)別是什么?
答:有DOM,SAX,STAX等
DOM:處理大型文件時(shí)其性能下降的非常厲害。這個(gè)問(wèn)題是由DOM的樹(shù)結(jié)構(gòu)所造成的,這種結(jié)構(gòu)占用的內(nèi)存較多,而且DOM必須在解析文件之前把整個(gè)文檔裝入內(nèi)存,適合對(duì)XML的隨機(jī)訪問(wèn)SAX:不現(xiàn)于DOM,SAX是事件驅(qū)動(dòng)型的XML解析方式。它順序讀取XML文件,不需要一次全部裝載整個(gè)文件。當(dāng)遇到像文件開(kāi)頭,文檔結(jié)束,或者標(biāo)簽開(kāi)頭與標(biāo)簽結(jié)束時(shí),它會(huì)觸發(fā)一個(gè)事件,用戶通過(guò)在其回調(diào)事件中寫(xiě)入處理代碼來(lái)處理XML文件,適合對(duì)XML的順序訪問(wèn)
STAX:Streaming API for XML (StAX)
講解這些區(qū)別是不需要特別去比較,就像說(shuō)傳智播客與其他培訓(xùn)機(jī)構(gòu)的區(qū)別時(shí),我們只需說(shuō)清楚傳智播客有什么特點(diǎn)和優(yōu)點(diǎn)就行了,這就已經(jīng)間接回答了彼此的區(qū)別。
126、你在項(xiàng)目中用到了xml技術(shù)的哪些方面?如何實(shí)現(xiàn)的?
答:用到了數(shù)據(jù)存貯,信息配置兩方面。在做數(shù)據(jù)交換平臺(tái)時(shí),將不能數(shù)據(jù)源的數(shù)據(jù)組裝成XML文件,然后將XML文件壓縮打包加密后通過(guò)網(wǎng)絡(luò)傳送給接收者,接收解密與解壓縮后再同XML文件中還原相關(guān)信息進(jìn)行處理。在做軟件配置時(shí),利用XML可以很方便的進(jìn)行,軟件的各種配置參數(shù)都存貯在XML文件中。
127、用jdom解析xml文件時(shí)如何解決中文問(wèn)題?如何解析?
答:看如下代碼,用編碼方式加以解決
package test;
import java.io.*;
public class DOMTest
{
private String inFile = "c:\\people.xml"
private String outFile = "c:\\people.xml"
public static void main(String args[])
{
new DOMTest();
}
public DOMTest()
{
try
{
javax.xml.parsers.DocumentBuilder builder =
javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder();
org.w3c.dom.Document doc = builder.newDocument();
org.w3c.dom.Element root = doc.createElement("老師");
org.w3c.dom.Element wang = doc.createElement("王");
org.w3c.dom.Element liu = doc.createElement("劉");
wang.appendChild(doc.createTextNode("我是王老師"));
root.appendChild(wang);
doc.appendChild(root);
javax.xml.transform.Transformer transformer =
javax.xml.transform.TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING, "gb2312");
transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes");
transformer.transform(new javax.xml.transform.dom.DOMSource(doc),
new
javax.xml.transform.stream.StreamResult(outFile));
}
catch (Exception e)
{
System.out.println (e.getMessage());
}
}
}
128、編程用JAVA解析XML的方式.
答:用SAX方式解析XML,XML文件如下:
<?xml version=1.0 encoding=gb2312?>
<person>
<name>王小明</name>
<college>信息學(xué)院</college>
<telephone>6258113</telephone>
<notes>男,1955年生,博士,95年調(diào)入海南大學(xué)</notes>
</person>
事件回調(diào)類SAXHandler.java
import java.io.*;
import java.util.Hashtable;
import org.xml.sax.*;
public class SAXHandler extends HandlerBase
{
private Hashtable table = new Hashtable();
private String currentElement = null;
private String currentValue = null;
public void setTable(Hashtable table)
{
this.table = table;
}
public Hashtable getTable()
{
return table;
}
public void startElement(String tag, AttributeList attrs)
throws SAXException
{
currentElement = tag;
}
public void characters(char[] ch, int start, int length)
throws SAXException
{
currentValue = new String(ch, start, length);
}
public void endElement(String name) throws SAXException
{
if (currentElement.equals(name))
table.put(currentElement, currentValue);
}
}
JSP內(nèi)容顯示源碼,SaxXml.jsp:
<HTML>
<HEAD>
<TITLE>剖析XML文件people.xml</TITLE>
</HEAD>
<BODY>
<%@ page errorPage=ErrPage.jsp
contentType=text/html;charset=GB2312 %>
<%@ page import=java.io.* %>
<%@ page import=java.util.Hashtable %>
<%@ page import=org.w3c.dom.* %>
<%@ page import=org.xml.sax.* %>
<%@ page import=javax.xml.parsers.SAXParserFactory %>
<%@ page import=javax.xml.parsers.SAXParser %>
<%@ page import=SAXHandler %>
<%
File file = new File(c:\people.xml);
FileReader reader = new FileReader(file);
Parser parser;
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
SAXHandler handler = new SAXHandler();
sp.parse(new InputSource(reader), handler);
Hashtable hashTable = handler.getTable();
out.println(<TABLE BORDER=2><CAPTION>教師信息表</CAPTION>);
out.println(<TR><TD>姓名</TD> + <TD> +
(String)hashTable.get(new String(name)) + </TD></TR>);
out.println(<TR><TD>學(xué)院</TD> + <TD> +
(String)hashTable.get(new String(college))+</TD></TR>);
out.println(<TR><TD>電話</TD> + <TD> +
(String)hashTable.get(new String(telephone)) + </TD></TR>);
out.println(<TR><TD>備注</TD> + <TD> +
(String)hashTable.get(new String(notes)) + </TD></TR>);
out.println(</TABLE>);
%>
</BODY>
</HTML>
129、XML文檔定義有幾種形式?它們之間有何本質(zhì)區(qū)別?解析XML文檔有哪幾種方式?
a: 兩種形式 dtd schema,b: 本質(zhì)區(qū)別:schema本身是xml的,可以被XML解析器解析(這也是從DTD上發(fā)展schema的根本目的),c:有DOM,SAX,STAX等
DOM:處理大型文件時(shí)其性能下降的非常厲害。這個(gè)問(wèn)題是由DOM的樹(shù)結(jié)構(gòu)所造成的,這種結(jié)構(gòu)占用的內(nèi)存較多,而且DOM必須在解析文件之前把整個(gè)文檔裝入內(nèi)存,適合對(duì)XML的隨機(jī)訪問(wèn)
SAX:不現(xiàn)于DOM,SAX是事件驅(qū)動(dòng)型的XML解析方式。它順序讀取XML文件,不需要一次全部裝載整個(gè)文件。當(dāng)遇到像文件開(kāi)頭,文檔結(jié)束,或者標(biāo)簽開(kāi)頭與標(biāo)簽結(jié)束時(shí),它會(huì)觸發(fā)一個(gè)事件,用戶通過(guò)在其回調(diào)事件中寫(xiě)入處理代碼來(lái)處理XML文件,適合對(duì)XML的順序訪問(wèn)
STAX:Streaming API for XML (StAX)
6. j2ee部分
130、BS與CS的聯(lián)系與區(qū)別。
C/S是Client/Server的縮寫(xiě)。服務(wù)器通常采用高性能的PC、工作站或小型機(jī),并采用大型數(shù)據(jù)庫(kù)系統(tǒng),如Oracle、Sybase、InFORMix或 SQL Server??蛻舳诵枰惭b專用的客戶端軟件。
B/S是Brower/Server的縮寫(xiě),客戶機(jī)上只要安裝一個(gè)瀏覽器(Browser),如Netscape Navigator或Internet Explorer,服務(wù)器安裝Oracle、Sybase、InFORMix或 SQL Server等數(shù)據(jù)庫(kù)。在這種結(jié)構(gòu)下,用戶界面完全通過(guò)WWW瀏覽器實(shí)現(xiàn),一部分事務(wù)邏輯在前端實(shí)現(xiàn),但是主要事務(wù)邏輯在服務(wù)器端實(shí)現(xiàn)。瀏覽器通過(guò)Web Server 同數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)交互。
C/S 與 B/S 區(qū)別:
1.硬件環(huán)境不同:
C/S 一般建立在專用的網(wǎng)絡(luò)上, 小范圍里的網(wǎng)絡(luò)環(huán)境, 局域網(wǎng)之間再通過(guò)專門(mén)服務(wù)器提供連接和數(shù)據(jù)交換服務(wù).
B/S 建立在廣域網(wǎng)之上的, 不必是專門(mén)的網(wǎng)絡(luò)硬件環(huán)境,例與電話上網(wǎng), 租用設(shè)備. 信息自己管理. 有比C/S更強(qiáng)的適應(yīng)范圍, 一般只要有操作系統(tǒng)和瀏覽器就行
2.對(duì)安全要求不同
C/S 一般面向相對(duì)固定的用戶群, 對(duì)信息安全的控制能力很強(qiáng). 一般高度機(jī)密的信息系統(tǒng)采用C/S 結(jié)構(gòu)適宜. 可以通過(guò)B/S發(fā)布部分可公開(kāi)信息.
B/S 建立在廣域網(wǎng)之上, 對(duì)安全的控制能力相對(duì)弱, 可能面向不可知的用戶。
3.對(duì)程序架構(gòu)不同
C/S 程序可以更加注重流程, 可以對(duì)權(quán)限多層次校驗(yàn), 對(duì)系統(tǒng)運(yùn)行速度可以較少考慮.
B/S 對(duì)安全以及訪問(wèn)速度的多重的考慮, 建立在需要更加優(yōu)化的基礎(chǔ)之上. 比C/S有更高的要求 B/S結(jié)構(gòu)的程序架構(gòu)是發(fā)展的趨勢(shì), 從MS的.Net系列的BizTalk 2000 Exchange 2000等, 全面支持網(wǎng)絡(luò)的構(gòu)件搭建的系統(tǒng). SUN 和IBM推的JavaBean 構(gòu)件技術(shù)等,使 B/S更加成熟.
4.軟件重用不同
C/S 程序可以不可避免的整體性考慮, 構(gòu)件的重用性不如在B/S要求下的構(gòu)件的重用性好.
B/S 對(duì)的多重結(jié)構(gòu),要求構(gòu)件相對(duì)獨(dú)立的功能. 能夠相對(duì)較好的重用.就入買(mǎi)來(lái)的餐桌可以再利用,而不是做在墻上的石頭桌子
5.系統(tǒng)維護(hù)不同
C/S 程序由于整體性, 必須整體考察, 處理出現(xiàn)的問(wèn)題以及系統(tǒng)升級(jí). 升級(jí)難. 可能是再做一個(gè)全新的系統(tǒng)
B/S 構(gòu)件組成,方面構(gòu)件個(gè)別的更換,實(shí)現(xiàn)系統(tǒng)的無(wú)縫升級(jí). 系統(tǒng)維護(hù)開(kāi)銷(xiāo)減到最小.用戶從網(wǎng)上自己下載安裝就可以實(shí)現(xiàn)升級(jí).
6.處理問(wèn)題不同
C/S 程序可以處理用戶面固定, 并且在相同區(qū)域, 安全要求高需求, 與操作系統(tǒng)相關(guān). 應(yīng)該都是相同的系統(tǒng)
B/S 建立在廣域網(wǎng)上, 面向不同的用戶群, 分散地域, 這是C/S無(wú)法作到的. 與操作系統(tǒng)平臺(tái)關(guān)系最小.
7.用戶接口不同
C/S 多是建立的Window平臺(tái)上,表現(xiàn)方法有限,對(duì)程序員普遍要求較高
B/S 建立在瀏覽器上, 有更加豐富和生動(dòng)的表現(xiàn)方式與用戶交流. 并且大部分難度減低,減低開(kāi)發(fā)成本.
8.信息流不同
C/S 程序一般是典型的中央集權(quán)的機(jī)械式處理, 交互性相對(duì)低
B/S 信息流向可變化, B-B B-C B-G等信息、流向的變化, 更像交易中心。
131、應(yīng)用服務(wù)器與WEB SERVER的區(qū)別?
應(yīng)用服務(wù)器:Weblogic、Tomcat、Jboss
WEB SERVER:IIS、 Apache
132、應(yīng)用服務(wù)器有那些?
BEA WebLogic Server,IBM WebSphere Application Server,Oracle9i Application Server,jBoss,Tomcat
133、J2EE是什么?
答:Je22是Sun公司提出的多層(multi-diered),分布式(distributed),基于組件(component-base)的企業(yè)級(jí)應(yīng)用模型(enterpriese application model).在這樣的一個(gè)應(yīng)用系統(tǒng)中,可按照功能劃分為不同的組件,這些組件又可在不同計(jì)算機(jī)上,并且處于相應(yīng)的層次(tier)中。所屬層次包括客戶層(clietn tier)組件,web層和組件,Business層和組件,企業(yè)信息系統(tǒng)(EIS)層。
一個(gè)另類的回答:j2ee就是增刪改查。
134、J2EE是技術(shù)還是平臺(tái)還是框架? 什么是J2EE
J2EE本身是一個(gè)標(biāo)準(zhǔn),一個(gè)為企業(yè)分布式應(yīng)用的開(kāi)發(fā)提供的標(biāo)準(zhǔn)平臺(tái)。
J2EE也是一個(gè)框架,包括JDBC、JNDI、RMI、JMS、EJB、JTA等技術(shù)。
135、請(qǐng)對(duì)以下在J2EE中常用的名詞進(jìn)行解釋(或簡(jiǎn)單描述)
web容器:給處于其中的應(yīng)用程序組件(JSP,SERVLET)提供一個(gè)環(huán)境,使JSP,SERVLET直接更容器中的環(huán)境變量接口交互,不必關(guān)注其它系統(tǒng)問(wèn)題。主要有WEB服務(wù)器來(lái)實(shí)現(xiàn)。例如:TOMCAT,WEBLOGIC,WEBSPHERE等。該容器提供的接口嚴(yán)格遵守J2EE規(guī)范中的WEB APPLICATION 標(biāo)準(zhǔn)。我們把遵守以上標(biāo)準(zhǔn)的WEB服務(wù)器就叫做J2EE中的WEB容器。
EJB容器:Enterprise java bean 容器。更具有行業(yè)領(lǐng)域特色。他提供給運(yùn)行在其中的組件EJB各種管理功能。只要滿足J2EE規(guī)范的EJB放入該容器,馬上就會(huì)被容器進(jìn)行高效率的管理。并且可以通過(guò)現(xiàn)成的接口來(lái)獲得系統(tǒng)級(jí)別的服務(wù)。例如郵件服務(wù)、事務(wù)管理。
JNDI:(Java Naming & Directory Interface)JAVA命名目錄服務(wù)。主要提供的功能是:提供一個(gè)目錄系統(tǒng),讓其它各地的應(yīng)用程序在其上面留下自己的索引,從而滿足快速查找和定位分布式應(yīng)用程序的功能。 (在連接池里面用到了)
JMS:(Java Message Service)JAVA消息服務(wù)。主要實(shí)現(xiàn)各個(gè)應(yīng)用程序之間的通訊。包括點(diǎn)對(duì)點(diǎn)和廣播。
JTA:(Java Transaction API)JAVA事務(wù)服務(wù)。提供各種分布式事務(wù)服務(wù)。應(yīng)用程序只需調(diào)用其提供的接口即可。
JAF:(Java Action FrameWork)JAVA安全認(rèn)證框架。提供一些安全控制方面的框架。讓開(kāi)發(fā)者通過(guò)各種部署和自定義實(shí)現(xiàn)自己的個(gè)性安全控制策略。
RMI/IIOP:(Remote Method Invocation /internet對(duì)象請(qǐng)求中介協(xié)議)他們主要用于通過(guò)遠(yuǎn)程調(diào)用服務(wù)。例如,遠(yuǎn)程有一臺(tái)計(jì)算機(jī)上運(yùn)行一個(gè)程序,它提供股票分析服務(wù),我們可以在本地計(jì)算機(jī)上實(shí)現(xiàn)對(duì)其直接調(diào)用。當(dāng)然這是要通過(guò)一定的規(guī)范才能在異構(gòu)的系統(tǒng)之間進(jìn)行通信。RMI是JAVA特有的。
136、如何給weblogic指定大小的內(nèi)存?
(這個(gè)問(wèn)題不作具體回答,列出來(lái)只是告訴讀者可能會(huì)遇到什么問(wèn)題,你不需要面面俱到,什么都精通。)(weblogic是BA公司的)
在啟動(dòng)Weblogic的腳本中(位于所在Domian對(duì)應(yīng)服務(wù)器目錄下的startServerName),增加set MEM_ARGS=-Xms32m -Xmx200m,可以調(diào)整最小內(nèi)存為32M,最大200M
137、如何設(shè)定的weblogic的熱啟動(dòng)模式(開(kāi)發(fā)模式)與產(chǎn)品發(fā)布模式?
可以在管理控制臺(tái)中修改對(duì)應(yīng)服務(wù)器的啟動(dòng)模式為開(kāi)發(fā)或產(chǎn)品模式之一?;蛘咝薷姆?wù)的啟動(dòng)文件或者commenv文件,增加set PRODUCTION_MODE=true。
138、如何啟動(dòng)時(shí)不需輸入用戶名與密碼?
修改服務(wù)啟動(dòng)文件,增加 WLS_USER和WLS_PW項(xiàng)。也可以在boot.properties文件中增加加密過(guò)的用戶名和密碼.
139、在weblogic管理制臺(tái)中對(duì)一個(gè)應(yīng)用域(或者說(shuō)是一個(gè)網(wǎng)站,Domain)進(jìn)行jms及ejb或連接池等相關(guān)信息進(jìn)行配置后,實(shí)際保存在什么文件中?
保存在此Domain的config.xml文件中,它是服務(wù)器的核心配置文件。
140、說(shuō)說(shuō)weblogic中一個(gè)Domain的缺省目錄結(jié)構(gòu)?比如要將一個(gè)簡(jiǎn)單的helloWorld.jsp放入何目錄下,然的在瀏覽器上就可打入http://主機(jī):端口號(hào)//helloword.jsp就可以看到運(yùn)行結(jié)果了? 又比如這其中用到了一個(gè)自己寫(xiě)的javaBean該如何辦?
Domain目錄服務(wù)器目錄applications,將應(yīng)用目錄放在此目錄下將可以作為應(yīng)用訪問(wèn),如果是Web應(yīng)用,應(yīng)用目錄需要滿足Web應(yīng)用目錄要求,jsp文件可以直接放在應(yīng)用目錄中,Javabean需要放在應(yīng)用目錄的WEB-INF目錄的classes目錄中,設(shè)置服務(wù)器的缺省應(yīng)用將可以實(shí)現(xiàn)在瀏覽器上無(wú)需輸入應(yīng)用名。
145、在weblogic中發(fā)布ejb需涉及到哪些配置文件
不同類型的EJB涉及的配置文件不同,都涉及到的配置文件包括ejb-jar.xml,weblogic-ejb-jar.xmlCMP實(shí)體Bean一般還需要weblogic-cmp-rdbms-jar.xml
146、如何在weblogic中進(jìn)行ssl配置與客戶端的認(rèn)證配置或說(shuō)說(shuō)j2ee(標(biāo)準(zhǔn))進(jìn)行ssl的配置?
缺省安裝中使用DemoIdentity.jks和DemoTrust.jks KeyStore實(shí)現(xiàn)SSL,需要配置服務(wù)器使用Enable SSL,配置其端口,在產(chǎn)品模式下需要從CA獲取私有密鑰和數(shù)字證書(shū),創(chuàng)建identity和trust keystore,裝載獲得的密鑰和數(shù)字證書(shū)。可以配置此SSL連接是單向還是雙向的。
147、如何查看在weblogic中已經(jīng)發(fā)布的EJB?
可以使用管理控制臺(tái),在它的Deployment中可以查看所有已發(fā)布的EJB
7. ejb部分
148、EJB是基于哪些技術(shù)實(shí)現(xiàn)的?并說(shuō)出SessionBean和EntityBean的區(qū)別,StatefulBean和StatelessBean的區(qū)別。
EJB包括Session Bean、Entity Bean、Message Driven Bean,基于JNDI、RMI、JAT等技術(shù)實(shí)現(xiàn)。
SessionBean在J2EE應(yīng)用程序中被用來(lái)完成一些服務(wù)器端的業(yè)務(wù)操作,例如訪問(wèn)數(shù)據(jù)庫(kù)、調(diào)用其他EJB組件。EntityBean被用來(lái)代表應(yīng)用系統(tǒng)中用到的數(shù)據(jù)。
對(duì)于客戶機(jī),SessionBean是一種非持久性對(duì)象,它實(shí)現(xiàn)某些在服務(wù)器上運(yùn)行的業(yè)務(wù)邏輯。
對(duì)于客戶機(jī),EntityBean是一種持久性對(duì)象,它代表一個(gè)存儲(chǔ)在持久性存儲(chǔ)器中的實(shí)體的對(duì)象視圖,或是一個(gè)由現(xiàn)有企業(yè)應(yīng)用程序?qū)崿F(xiàn)的實(shí)體。
Session Bean 還可以再細(xì)分為 Tasteful Session Bean 與 Stateless Session Bean ,這兩種的 Session Bean都可以將系統(tǒng)邏輯放在 method之中執(zhí)行,不同的是 Stateful Session Bean 可以記錄呼叫者的狀態(tài),因此通常來(lái)說(shuō),一個(gè)使用者會(huì)有一個(gè)相對(duì)應(yīng)的 Stateful Session Bean 的實(shí)體。Stateless Session Bean 雖然也是邏輯組件,但是他卻不負(fù)責(zé)記錄使用者狀態(tài),也就是說(shuō)當(dāng)使用者呼叫 Stateless Session Bean 的時(shí)候,EJB Container 并不會(huì)找尋特定的 Stateless Session Bean 的實(shí)體來(lái)執(zhí)行這個(gè) method。換言之,很可能數(shù)個(gè)使用者在執(zhí)行某個(gè) Stateless Session Bean 的 methods 時(shí),會(huì)是同一個(gè) Bean 的 Instance 在執(zhí)行。從內(nèi)存方面來(lái)看, Stateful Session Bean 與 Stateless Session Bean 比較, Stateful Session Bean 會(huì)消耗 J2EE Server 較多的內(nèi)存,然而 Stateful Session Bean 的優(yōu)勢(shì)卻在于他可以維持使用者的狀態(tài)。
149、簡(jiǎn)要講一下 EJB 的 7 個(gè) Transaction Level?
150、EJB與JAVA BEAN的區(qū)別?
Java Bean 是可復(fù)用的組件,對(duì)Java Bean并沒(méi)有嚴(yán)格的規(guī)范,理論上講,任何一個(gè)Java類都可以是一個(gè)Bean。但通常情況下,由于Java Bean是被容器所創(chuàng)建(如Tomcat)的,所以Java Bean應(yīng)具有一個(gè)無(wú)參的構(gòu)造器,另外,通常Java Bean還要實(shí)現(xiàn)Serializable接口用于實(shí)現(xiàn)Bean的持久性。Java Bean實(shí)際上相當(dāng)于微軟COM模型中的本地進(jìn)程內(nèi)COM組件,它是不能被跨進(jìn)程訪問(wèn)的。Enterprise Java Bean 相當(dāng)于DCOM,即分布式組件。它是基于Java的遠(yuǎn)程方法調(diào)用(RMI)技術(shù)的,所以EJB可以被遠(yuǎn)程訪問(wèn)(跨進(jìn)程、跨計(jì)算機(jī))。但EJB必須被布署在諸如Webspere、WebLogic這樣的容器中,EJB客戶從不直接訪問(wèn)真正的EJB組件,而是通過(guò)其容器訪問(wèn)。EJB容器是EJB組件的代理,EJB組件由容器所創(chuàng)建和管理。客戶通過(guò)容器來(lái)訪問(wèn)真正的EJB組件。
151、EJB包括(SessionBean,EntityBean)說(shuō)出他們的生命周期,及如何管理事務(wù)的?
SessionBean:Stateless Session Bean 的生命周期是由容器決定的,當(dāng)客戶機(jī)發(fā)出請(qǐng)求要建立一個(gè)Bean的實(shí)例時(shí),EJB容器不一定要?jiǎng)?chuàng)建一個(gè)新的Bean的實(shí)例供客戶機(jī)調(diào)用,而是隨便找一個(gè)現(xiàn)有的實(shí)例提供給客戶機(jī)。當(dāng)客戶機(jī)第一次調(diào)用一個(gè)Stateful Session Bean 時(shí),容器必須立即在服務(wù)器中創(chuàng)建一個(gè)新的Bean實(shí)例,并關(guān)聯(lián)到客戶機(jī)上,以后此客戶機(jī)調(diào)用Stateful Session Bean 的方法時(shí)容器會(huì)把調(diào)用分派到與此客戶機(jī)相關(guān)聯(lián)的Bean實(shí)例。
EntityBean:Entity Beans能存活相對(duì)較長(zhǎng)的時(shí)間,并且狀態(tài)是持續(xù)的。只要數(shù)據(jù)庫(kù)中的數(shù)據(jù)存在,Entity beans就一直存活。而不是按照應(yīng)用程序或者服務(wù)進(jìn)程來(lái)說(shuō)的。即使EJB容器崩潰了,Entity beans也是存活的。Entity Beans生命周期能夠被容器或者 Beans自己管理。
EJB通過(guò)以下技術(shù)管理實(shí)務(wù):對(duì)象管理組織(OMG)的對(duì)象實(shí)務(wù)服務(wù)(OTS),Sun Microsystems的Transaction Service(JTS)、Java Transaction API(JTA),開(kāi)發(fā)組(X/Open)的XA接口。
152、EJB容器提供的服務(wù)
主要提供聲明周期管理、代碼產(chǎn)生、持續(xù)性管理、安全、事務(wù)管理、鎖和并發(fā)行管理等服務(wù)。
153、EJB的激活機(jī)制
以Stateful Session Bean 為例:其Cache大小決定了內(nèi)存中可以同時(shí)存在的Bean實(shí)例的數(shù)量,根據(jù)MRU或NRU算法,實(shí)例在激活和去激活狀態(tài)之間遷移,激活機(jī)制是當(dāng)客戶端調(diào)用某個(gè)EJB實(shí)例業(yè)務(wù)方法時(shí),如果對(duì)應(yīng)EJB Object發(fā)現(xiàn)自己沒(méi)有綁定對(duì)應(yīng)的Bean實(shí)例則從其去激活Bean存儲(chǔ)中(通過(guò)序列化機(jī)制存儲(chǔ)實(shí)例)回復(fù)(激活)此實(shí)例。狀態(tài)變遷前會(huì)調(diào)用對(duì)應(yīng)的ejbActive和ejbPassivate方法。
154、EJB的幾種類型
會(huì)話(Session)Bean ,實(shí)體(Entity)Bean 消息驅(qū)動(dòng)的(Message Driven)Bean
會(huì)話Bean又可分為有狀態(tài)(Stateful)和無(wú)狀態(tài)(Stateless)兩種
實(shí)體Bean可分為Bean管理的持續(xù)性(BMP)和容器管理的持續(xù)性(CMP)兩種
155、客服端調(diào)用EJB對(duì)象的幾個(gè)基本步驟
設(shè)置JNDI服務(wù)工廠以及JNDI服務(wù)地址系統(tǒng)屬性,查找Home接口,從Home接口調(diào)用Create方法創(chuàng)建Remote接口,通過(guò)Remote接口調(diào)用其業(yè)務(wù)方法。
156. webservice部分
157、WEB SERVICE名詞解釋。JSWDL開(kāi)發(fā)包的介紹。JAXP、JAXM的解釋。SOAP、UDDI,WSDL解釋。
Web ServiceWeb Service是基于網(wǎng)絡(luò)的、分布式的模塊化組件,它執(zhí)行特定的任務(wù),遵守具體的技術(shù)規(guī)范,這些規(guī)范使得Web Service能與其他兼容的組件進(jìn)行互操作。
JAXP(Java API for XML Parsing) 定義了在Java中使用DOM, SAX, XSLT的通用的接口。這樣在你的程序中你只要使用這些通用的接口,當(dāng)你需要改變具體的實(shí)現(xiàn)時(shí)候也不需要修改代碼。
JAXM(Java API for XML Messaging) 是為SOAP通信提供訪問(wèn)方法和傳輸機(jī)制的API。
WSDL是一種 XML 格式,用于將網(wǎng)絡(luò)服務(wù)描述為一組端點(diǎn),這些端點(diǎn)對(duì)包含面向文檔信息或面向過(guò)程信息的消息進(jìn)行操作。這種格式首先對(duì)操作和消息進(jìn)行抽象描述,然后將其綁定到具體的網(wǎng)絡(luò)協(xié)議和消息格式上以定義端點(diǎn)。相關(guān)的具體端點(diǎn)即組合成為抽象端點(diǎn)(服務(wù))。
SOAP即簡(jiǎn)單對(duì)象訪問(wèn)協(xié)議(Simple Object Access Protocol),它是用于交換XML編碼信息的輕量級(jí)協(xié)議。
UDDI 的目的是為電子商務(wù)建立標(biāo)準(zhǔn);UDDI是一套基于Web的、分布式的、為Web Service提供的、信息注冊(cè)中心的實(shí)現(xiàn)標(biāo)準(zhǔn)規(guī)范,同時(shí)也包含一組使企業(yè)能將自身提供的Web Service注冊(cè),以使別的企業(yè)能夠發(fā)現(xiàn)的訪問(wèn)協(xié)議的實(shí)現(xiàn)標(biāo)準(zhǔn)。
158、CORBA是什么?用途是什么?
CORBA 標(biāo)準(zhǔn)是公共對(duì)象請(qǐng)求代理結(jié)構(gòu)(Common Object Request Broker Architecture),由對(duì)象管理組織 (Object Management Group,縮寫(xiě)為 OMG)標(biāo)準(zhǔn)化。它的組成是接口定義語(yǔ)言(IDL), 語(yǔ)言綁定(binding:也譯為聯(lián)編)和允許應(yīng)用程序間互操作的協(xié)議。 其目的為:用不同的程序設(shè)計(jì)語(yǔ)言書(shū)寫(xiě)在不同的進(jìn)程中運(yùn)行,為不同的操作系統(tǒng)開(kāi)發(fā)。
5. 流行的框架與新技術(shù)
159、談?wù)凷truts中的Action servlet。
屬于是中央控制器,所有的請(qǐng)求都由Action servlet解析,當(dāng)是他也不是每一個(gè)都自己取解析,
而是交給他的手下
160、Struts優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
1. 實(shí)現(xiàn)MVC模式,結(jié)構(gòu)清晰,使開(kāi)發(fā)者只關(guān)注業(yè)務(wù)邏輯的實(shí)現(xiàn).
2.有豐富的tag可以用 ,Struts的標(biāo)記庫(kù)(Taglib),如能靈活動(dòng)用,則能大大提高開(kāi)發(fā)效率
3. 頁(yè)面導(dǎo)航
使系統(tǒng)的脈絡(luò)更加清晰。通過(guò)一個(gè)配置文件,即可把握整個(gè)系統(tǒng)各部分之間的聯(lián)系,這對(duì)于后期的維護(hù)有著莫大的好處。尤其是當(dāng)另一批開(kāi)發(fā)者接手這個(gè)項(xiàng)目時(shí),這種優(yōu)勢(shì)體現(xiàn)得更加明顯。
4. 提供Exception處理機(jī)制 .
5. 數(shù)據(jù)庫(kù)鏈接池管理
6. 支持I18N
缺點(diǎn)
一、 轉(zhuǎn)到展示層時(shí),需要配置forward,如果有十個(gè)展示層的jsp,需要配置十次struts,而且還不包括有時(shí)候目錄、文件變更,需要重新修改forward,注意,每次修改配置之后,要求重新部署整個(gè)項(xiàng)目,而tomcate這樣的服務(wù)器,還必須重新啟動(dòng)服務(wù)器
二、 二、 Struts 的Action必需是thread-safe方式,它僅僅允許一個(gè)實(shí)例去處理所有的請(qǐng)求。所以action用到的所有的資源都必需統(tǒng)一同步,這個(gè)就引起了線程安全的問(wèn)題。
三、 測(cè)試不方便. Struts的每個(gè)Action都同Web層耦合在一起,這樣它的測(cè)試依賴于Web容器,單元測(cè)試也很難實(shí)現(xiàn)。不過(guò)有一個(gè)Junit的擴(kuò)展工具Struts TestCase可以實(shí)現(xiàn)它的單元測(cè)試。
四、 類型的轉(zhuǎn)換. Struts的FormBean把所有的數(shù)據(jù)都作為String類型,它可以使用工具Commons-Beanutils進(jìn)行類型轉(zhuǎn)化。但它的轉(zhuǎn)化都是在Class級(jí)別,而且轉(zhuǎn)化的類型是不可配置的。類型轉(zhuǎn)化時(shí)的錯(cuò)誤信息返回給用戶也是非常困難的。
五、 對(duì)Servlet的依賴性過(guò)強(qiáng). Struts處理Action時(shí)必需要依賴ServletRequest 和ServletResponse,所有它擺脫不了Servlet容器。
六、 前端表達(dá)式語(yǔ)言方面.Struts集成了JSTL,所以它主要使用JSTL的表達(dá)式語(yǔ)言來(lái)獲取數(shù)據(jù)??墒荍STL的表達(dá)式語(yǔ)言在Collection和索引屬性方面處理顯得很弱。
七、 對(duì)Action執(zhí)行的控制困難. Struts創(chuàng)建一個(gè)Action,如果想控制它的執(zhí)行順序?qū)?huì)非常困難。甚至你要重新去寫(xiě)Servlet來(lái)實(shí)現(xiàn)你的這個(gè)功能需求。
八、 對(duì)Action 執(zhí)行前和后的處理. Struts處理Action的時(shí)候是基于class的hierarchies,很難在action處理前和后進(jìn)行操作。
九、 對(duì)事件支持不夠. 在struts中,實(shí)際是一個(gè)表單Form對(duì)應(yīng)一個(gè)Action類(或DispatchAction),換一句話說(shuō):在Struts中實(shí)際是一個(gè)表單只能 對(duì)應(yīng)一個(gè)事件,struts這種事件方式稱為application event,application event和component event相比是一種粗粒度的事件
161、STRUTS的應(yīng)用(如STRUTS架構(gòu))
Struts是采用Java Servlet/JavaServer Pages技術(shù),開(kāi)發(fā)Web應(yīng)用程序的開(kāi)放源碼的framework。 采用Struts能開(kāi)發(fā)出基于MVC(Model-View-Controller)設(shè)計(jì)模式的應(yīng)用構(gòu)架。 Struts有如下的主要功能: 一.包含一個(gè)controller servlet,能將用戶的請(qǐng)求發(fā)送到相應(yīng)的Action對(duì)象。 二.JSP自由tag庫(kù),并且在controller servlet中提供關(guān)聯(lián)支持,幫助開(kāi)發(fā)員創(chuàng)建交互式表單應(yīng)用。 三.提供了一系列實(shí)用對(duì)象:XML處理、通過(guò)Java reflection APIs自動(dòng)處理JavaBeans屬性、國(guó)際化的提示和消息。
162、hibernate中的update()和saveOrUpdate()的區(qū)別,session的load()和get()的區(qū)別。
163、簡(jiǎn)述 Hibernate 和 JDBC 的優(yōu)缺點(diǎn)? 如何書(shū)寫(xiě)一個(gè) one to many 配置文件.
164、iBatis與Hibernate有什么不同?
相同點(diǎn):屏蔽jdbc api的底層訪問(wèn)細(xì)節(jié),使用我們不用與jdbc api 打交道,就可以訪問(wèn)數(shù)據(jù),jdbc api編程流程固定,
165. hibernate進(jìn)行多表查詢每個(gè)表中各取幾個(gè)字段,也就是說(shuō)查詢出來(lái)的結(jié)果集沒(méi)有一個(gè)實(shí)體類與之對(duì)應(yīng)如何解決;
解決方案一,按照Object[]數(shù)據(jù)取出數(shù)據(jù),然后自己組bean
解決方案二,對(duì)每個(gè)表的bean寫(xiě)構(gòu)造函數(shù),比如表一要查出field1,field2兩個(gè)字段,那么有一個(gè)構(gòu)造函數(shù)就是Bean(type1 filed1,type2
field2) ,然后在hql里面就可以直接生成這個(gè)bean了。
166.介紹一下Hibernate的二級(jí)緩存
按照以下思路來(lái)回答:(1)首先說(shuō)清楚什么是緩存,(2)再說(shuō)有了hibernate的Session就是一級(jí)緩存,即有了一級(jí)緩存,為什么還要有二級(jí)緩存,(3)最后再說(shuō)如何配置Hibernate的二級(jí)緩存。
(1)緩存就是把以前從數(shù)據(jù)庫(kù)中查詢出來(lái)和使用過(guò)的對(duì)象保存在內(nèi)存中(一個(gè)數(shù)據(jù)結(jié)構(gòu)中),這個(gè)數(shù)據(jù)結(jié)構(gòu)通常是或類似Hashmap,當(dāng)以后要使用某個(gè)對(duì)象時(shí),先查詢緩存中是否有這個(gè)對(duì)象,如果有則使用緩存中的對(duì)象,如果沒(méi)有則去查詢數(shù)據(jù)庫(kù),并將查詢出來(lái)的對(duì)象保存在緩存中,以便下次使用。下面是緩存的偽代碼:
引出hibernate的第二級(jí)緩存,用下面的偽代碼分析了Cache的實(shí)現(xiàn)原理
Dao
{
hashmap map = new map();
User getUser(integer id)
{
User user = map.get(id)
if(user == null)
{
user = session.get(id);
map.put(id,user);
}
return user;
}
}
Dao
{
Cache cache = null
setCache(Cache cache)
{
this.cache = cache
}
User getUser(int id)
{
if(cache!=null)
{
User user = cache.get(id);
if(user ==null)
{
user = session.get(id);
cache.put(id,user);
}
return user;
}
return session.get(id);
}
}
(2)Hibernate的Session就是一種緩存,我們通常將之稱為Hibernate的一級(jí)緩存,當(dāng)想使用session從數(shù)據(jù)庫(kù)中查詢出一個(gè)對(duì)象時(shí),Session也是先從自己內(nèi)部查看是否存在這個(gè)對(duì)象,存在則直接返回,不存在才去訪問(wèn)數(shù)據(jù)庫(kù),并將查詢的結(jié)果保存在自己內(nèi)部。由于Session代表一次會(huì)話過(guò)程,一個(gè)Session與一個(gè)數(shù)據(jù)庫(kù)連接相關(guān)連,所以Session最好不要長(zhǎng)時(shí)間保持打開(kāi),通常僅用于一個(gè)事務(wù)當(dāng)中,在事務(wù)結(jié)束時(shí)就應(yīng)關(guān)閉。并且Session是線程不安全的,被多個(gè)線程共享時(shí)容易出現(xiàn)問(wèn)題。通常只有那種全局意義上的緩存才是真正的緩存應(yīng)用,才有較大的緩存價(jià)值,因此,Hibernate的Session這一級(jí)緩存的緩存作用并不明顯,應(yīng)用價(jià)值不大。Hibernate的二級(jí)緩存就是要為Hibernate配置一種全局緩存,讓多個(gè)線程和多個(gè)事務(wù)都可以共享這個(gè)緩存。我們希望的是一個(gè)人使用過(guò),其他人也可以使用,session沒(méi)有這種效果。
(3)二級(jí)緩存是獨(dú)立于Hibernate的軟件部件,屬于第三方的產(chǎn)品,多個(gè)廠商和組織都提供有緩存產(chǎn)品,例如,EHCache和OSCache等等。在Hibernate中使用二級(jí)緩存,首先就要在hibernate.cfg.xml配置文件中配置使用哪個(gè)廠家的緩存產(chǎn)品,接著需要配置該緩存產(chǎn)品自己的配置文件,最后要配置Hibernate中的哪些實(shí)體對(duì)象要納入到二級(jí)緩存的管理中。明白了二級(jí)緩存原理和有了這個(gè)思路后,很容易配置起Hibernate的二級(jí)緩存。擴(kuò)展知識(shí):一個(gè)SessionFactory可以關(guān)聯(lián)一個(gè)二級(jí)緩存,也即一個(gè)二級(jí)緩存只能負(fù)責(zé)緩存一個(gè)數(shù)據(jù)庫(kù)中的數(shù)據(jù),當(dāng)使用Hibernate 的二級(jí)緩存后,注意不要有其他的應(yīng)用或SessionFactory來(lái)更改當(dāng)前數(shù)據(jù)庫(kù)中的數(shù)據(jù),這樣緩存的數(shù)據(jù)就會(huì)與數(shù)據(jù)庫(kù)中的實(shí)際數(shù)據(jù)不一致。
167、Spring 的依賴注入是什么意思? 給一個(gè) Bean 的 message 屬性, 字符串類型, 注入值為 "Hello" 的 XML 配置文件該怎么寫(xiě)?
168、Jdo是什么?
JDO是Java對(duì)象持久化的新的規(guī)范,為java data object的簡(jiǎn)稱,也是一個(gè)用于存取某種數(shù)據(jù)倉(cāng)庫(kù)中的對(duì)象的標(biāo)準(zhǔn)化API。JDO提供了透明的對(duì)象存儲(chǔ),因此對(duì)開(kāi)發(fā)人員來(lái)說(shuō),存儲(chǔ)數(shù)據(jù)對(duì)象完全不需要額外的代碼(如JDBC API的使用)。這些繁瑣的例行工作已經(jīng)轉(zhuǎn)移到JDO產(chǎn)品提供商身上,使開(kāi)發(fā)人員解脫出來(lái),從而集中時(shí)間和精力在業(yè)務(wù)邏輯上。另外,JDO很靈活,因?yàn)樗梢栽谌魏螖?shù)據(jù)底層上運(yùn)行。JDBC只是面向關(guān)系數(shù)據(jù)庫(kù)(RDBMS)JDO更通用,提供到任何數(shù)據(jù)底層的存儲(chǔ)功能,比如關(guān)系數(shù)據(jù)庫(kù)、文件、XML以及對(duì)象數(shù)據(jù)庫(kù)(ODBMS)等等,使得應(yīng)用可移植性更強(qiáng)。
169、什么是spring的IOC AOP
Spring要掌握的:
一個(gè)就是IOC(依賴注入(耦合程度可以降低)或者控制反轉(zhuǎn))一個(gè)就是AOP
170、STRUTS的工作流程!
171、spring 與EJB的區(qū)別??!
9. 軟件工程與設(shè)計(jì)模式
172、UML方面
標(biāo)準(zhǔn)建模語(yǔ)言UML。用例圖,靜態(tài)圖(包括類圖、對(duì)象圖和包圖),行為圖,交互圖(順序圖,合作圖),實(shí)現(xiàn)圖。
173. 軟件開(kāi)發(fā)的
174、j2ee常用的設(shè)計(jì)模式?說(shuō)明工廠模式。
總共23種,分為三大類:創(chuàng)建型,結(jié)構(gòu)型,行為型
我只記得其中常用的6、7種,分別是:
創(chuàng)建型(工廠、工廠方法、抽象工廠、單例)
結(jié)構(gòu)型(包裝、適配器,組合,代理)
行為(觀察者,模版,策略)
然后再針對(duì)你熟悉的模式談?wù)勀愕睦斫饧纯伞?nbsp;
Java中的23種設(shè)計(jì)模式:
Factory(工廠模式), Builder(建造模式), Factory Method(工廠方法模式),
Prototype(原始模型模式),Singleton(單例模式), Facade(門(mén)面模式),
Adapter(適配器模式), Bridge(橋梁模式), Composite(合成模式),
Decorator(裝飾模式), Flyweight(享元模式), Proxy(代理模式),
Command(命令模式), Interpreter(解釋器模式), Visitor(訪問(wèn)者模式),
Iterator(迭代子模式), Mediator(調(diào)停者模式), Memento(備忘錄模式),
Observer(觀察者模式), State(狀態(tài)模式), Strategy(策略模式),
Template Method(模板方法模式), Chain Of Responsibleity(責(zé)任鏈模式)
工廠模式:工廠模式是一種經(jīng)常被使用到的模式,根據(jù)工廠模式實(shí)現(xiàn)的類可以根據(jù)提供的數(shù)據(jù)生成一組類中某一個(gè)類的實(shí)例,通常這一組類有一個(gè)公共的抽象父類并且實(shí)現(xiàn)了相同的方法,但是這些方法針對(duì)不同的數(shù)據(jù)進(jìn)行了不同的操作。首先需要定義一個(gè)基類,該類的子類通過(guò)不同的方法實(shí)現(xiàn)了基類中的方法。然后需要定義一個(gè)工廠類,工廠類可以根據(jù)條件生成不同的子類實(shí)例。當(dāng)?shù)玫阶宇惖膶?shí)例后,開(kāi)發(fā)人員可以調(diào)用基類中的方法而不必考慮到底返回的是哪一個(gè)子類的實(shí)例。
175、開(kāi)發(fā)中都用到了那些設(shè)計(jì)模式?用在什么場(chǎng)合?
每個(gè)模式都描述了一個(gè)在我們的環(huán)境中不斷出現(xiàn)的問(wèn)題,然后描述了該問(wèn)題的解決方案的核心。通過(guò)這種方式,你可以無(wú)數(shù)次地使用那些已有的解決方案,無(wú)需在重復(fù)相同的工作。主要用到了MVC的設(shè)計(jì)模式。用來(lái)開(kāi)發(fā)JSP/Servlet或者J2EE的相關(guān)應(yīng)用。簡(jiǎn)單工廠模式等。
10. Linux
176、LINUX下線程,GDI類的解釋。
LINUX實(shí)現(xiàn)的就是基于核心輕量級(jí)進(jìn)程的"一對(duì)一"線程模型,一個(gè)線程實(shí)體對(duì)應(yīng)一個(gè)核心輕量級(jí)進(jìn)程,而線程之間的管理在核外函數(shù)庫(kù)中實(shí)現(xiàn)。
GDI類為圖像設(shè)備編程接口類庫(kù)。
10. 問(wèn)得稀里糊涂的題
177、四種會(huì)話跟蹤技術(shù)
會(huì)話作用域ServletsJSP 頁(yè)面描述
page否是代表與一個(gè)頁(yè)面相關(guān)的對(duì)象和屬性。一個(gè)頁(yè)面由一個(gè)編譯好的 Java servlet 類(可以帶有任何的 include 指令,但是沒(méi)有 include 動(dòng)作)表示。這既包括 servlet 又包括被編譯成 servlet 的 JSP 頁(yè)面
request是是代表與 Web 客戶機(jī)發(fā)出的一個(gè)請(qǐng)求相關(guān)的對(duì)象和屬性。一個(gè)請(qǐng)求可能跨越多個(gè)頁(yè)面,涉及多個(gè) Web 組件(由于 forward 指令和 include 動(dòng)作的關(guān)系)
session是是代表與用于某個(gè) Web 客戶機(jī)的一個(gè)用戶體驗(yàn)相關(guān)的對(duì)象和屬性。一個(gè) Web 會(huì)話可以也經(jīng)常會(huì)跨越多個(gè)客戶機(jī)請(qǐng)求
application是是代表與整個(gè) Web 應(yīng)用程序相關(guān)的對(duì)象和屬性。這實(shí)質(zhì)上是跨越整個(gè) Web 應(yīng)用程序,包括多個(gè)頁(yè)面、請(qǐng)求和會(huì)話的一個(gè)全局作用域
178、簡(jiǎn)述邏輯操作(&,|,^)與條件操作(&&,||)的區(qū)別。
區(qū)別主要答兩點(diǎn):a.條件操作只能操作布爾型的,而邏輯操作不僅可以操作布爾型,而且可以操作數(shù)值型
b.邏輯操作不會(huì)產(chǎn)生短路
10. 其他
179、請(qǐng)用英文簡(jiǎn)單介紹一下自己.
4、WEB SERVICE名詞解釋。JSWDL開(kāi)發(fā)包的介紹。JAXP、JAXM的解釋。SOAP、UDDI,WSDL解釋。
180、請(qǐng)把 http://tomcat.apache.org/ 首頁(yè)的這一段話用中文翻譯一下?
Apache Tomcat is the servlet container that is used in the official Reference Implementation for the Java Servlet and JavaServer Pages technologies. The Java Servlet and JavaServer Pages specifications are developed by Sun under the Java Community Process.
Apache Tomcat is developed in an open and participatory environment and released under the Apache Software License. Apache Tomcat is intended to be a collaboration of the best-of-breed developers from around the world. We invite you to participate in this open development project. To learn more about getting involved, click here.
Apache Tomcat powers numerous large-scale, mission-critical web applications across a diverse range of industries and organizations. Some of these users and their stories are listed on the PoweredBy wiki page.
180、美資軟件公司JAVA工程師電話面試題目
1. Talk about overriding, overloading.
2. Talk about JAVA design patterns you known.
3. Talk about the difference between LinkList, ArrayList and Victor.
4. Talk about the difference between an Abstract class and an Interface.
5. Class a = new Class(); Class b = new Class();
if(a == b) returns true or false, why?
6. Why we use StringBuffer when concatenating strings?
7. Try to explain Singleton to us? Is it thread safe? If no, how to make it thread safe?
8. Try to explain Ioc?
9. How to set many-to-many relationship in Hibernate?
10. Talk about the difference between INNER JOIN and LFET JOIN.
11. Why we use index in database? How many indexes is the maximum in one table as your suggestion?
12. When ‘Final’ is used in class, method and property, what dose it mean?
13. Do you have any experience on XML? Talk about any XML tool you used ,e.g. JAXB, JAXG.
14. Do you have any experience on Linux?
15. In OOD what is the reason when you create a Sequence diagram?
作者:chen.yu
深信服三年半工作經(jīng)驗(yàn),目前就職游戲廠商,希望能和大家交流和學(xué)習(xí),
微信公眾號(hào):編程入門(mén)到禿頭 或掃描下面二維碼
零基礎(chǔ)入門(mén)進(jìn)階人工智能(鏈接)