java宝典
說明,為了減輕大家的負(fù)擔(dān)和節(jié)省大家的時(shí)間,一些過時(shí)知識(shí)點(diǎn)和被筆試概率極低的題目不再被收錄和分析。
回答問題的思路:先正面敘述一些基本的核心知識(shí),然后描述一些特殊的東西,最后再來一些錦上添花的東西。要注意有些不是錦上添花,而是畫蛇添足的東西,不要隨便寫上。把答題像寫書一樣寫。我要回答一個(gè)新技術(shù)的問題大概思路和步驟是:我們想干什么,干這個(gè)遇到了什么問題,現(xiàn)在用什么方式來解決。其實(shí)我們講課也是這樣一個(gè)思路。
例如,將ajax時(shí),我們希望不改變?cè)瓉淼恼麄€(gè)網(wǎng)頁,而知識(shí)改變網(wǎng)頁中的局部?jī)?nèi)容,例如,用戶名校驗(yàn),級(jí)聯(lián)下拉列表,下來樹狀菜單。用傳統(tǒng)方式,就是瀏覽器自己直接向服務(wù)器發(fā)請(qǐng)求,服務(wù)器返回新頁面回蓋掉老頁面,這樣就不流暢了。
?
對(duì)于這個(gè)系列里的問題,每個(gè)學(xué)Java的人都應(yīng)該搞懂。當(dāng)然,如果只是學(xué)Java玩玩就無所謂了。如果你認(rèn)為自己已經(jīng)超越初學(xué)者了,卻不很懂這些問題,請(qǐng)將你自己重歸初學(xué)者行列。
答題時(shí),先答是什么,再答有什么作用和要注意什么(這部分最重要,展現(xiàn)自己的心得)
?
答案的段落分別,層次分明,條理清楚都非常重要,從這些表面的東西也可以看出一個(gè)人的習(xí)慣、辦事風(fēng)格、條理等。
要將你做出答案的思路過程,或者說你記住答案的思想都寫下來。把答題想著是辯論賽。答題就是給別人講道理、擺事實(shí)。答題不局限于什么格式和形式,就是要將自己的學(xué)識(shí)展現(xiàn)出來!
別因?yàn)槿思翌}目本來就模棱兩可,你就心里膽怯和沒底氣了,不敢回答了。你要大膽地指出對(duì)方題目很模糊和你的觀點(diǎn),不要把面試官想得有多高,其實(shí)他和你就是差不多的,你想想,如果他把你招進(jìn)去了,你們以后就是同事了,可不是差不多的嗎?
關(guān)于就業(yè)薪水,如果你是應(yīng)屆生,那不能要高工資,好比大餅的故事,要拿高工資,就去中關(guān)村!少數(shù)人基礎(chǔ)確實(shí)很好,在校期間確實(shí)又做過一些項(xiàng)目,那仍然是可以要到相對(duì)高的工資的。基礎(chǔ)好的冷桂華的故事。
初級(jí)程序員薪水:2000-4500
中級(jí)程序員薪水:4000-7000
高級(jí)程序員薪水:7000以上
?
公司招聘程序員更看重的要用到的編碼技術(shù)、而不是那些業(yè)務(wù)不太相關(guān)的所謂項(xiàng)目經(jīng)歷:
1.公司想招什么樣的人2.公司面試會(huì)問什么,.3.簡(jiǎn)歷怎么寫4怎樣達(dá)到簡(jiǎn)歷上的標(biāo)準(zhǔn)(培訓(xùn)中心教項(xiàng)目的目的)
?
對(duì)于一些公司接到了一些項(xiàng)目,想招聘一些初中級(jí)的程序員過來幫助寫代碼,完成這個(gè)項(xiàng)目,你更看重的是他的專業(yè)技術(shù)功底,還是以前做過幾個(gè)項(xiàng)目的經(jīng)歷呢?我們先排除掉那些編碼技術(shù)功底好,又正好做過相似項(xiàng)目的情況,實(shí)際上,這種魚和熊掌兼得的情況并不常見。其實(shí)公司很清楚,只要招聘進(jìn)來的人技術(shù)真的很明白,那他什么項(xiàng)目都可以做出來,公司招人不是讓你去重復(fù)做你以前的項(xiàng)目,而是做一個(gè)新項(xiàng)目,業(yè)務(wù)方面,你只要進(jìn)了項(xiàng)目團(tuán)隊(duì),自然就能掌握。所以,大多數(shù)招聘單位在招聘那些編碼級(jí)別的程序員時(shí)也沒指望能招聘到做過類似項(xiàng)目的人,也不會(huì)刻意去找做過類似項(xiàng)目的人,用人單位也不是想把你招進(jìn),然后把你以前做過的項(xiàng)目重做一遍,所以,用人單位更看重招進(jìn)來的人對(duì)要用到的編碼技術(shù)的功底到底怎樣,技術(shù)扎實(shí)不扎實(shí),項(xiàng)目則只要跟著開發(fā)團(tuán)隊(duì)走,自然就沒問題。除非是一些非常專業(yè)的行業(yè),要招聘特別高級(jí)的開發(fā)人員和系統(tǒng)分析師,招聘單位才特別注重他的項(xiàng)目經(jīng)驗(yàn)和行業(yè)經(jīng)驗(yàn),要去找到行業(yè)高手,公司才關(guān)心項(xiàng)目和與你聊項(xiàng)目的細(xì)節(jié),這樣的人通常都不是通過常規(guī)招聘渠道去招聘進(jìn)來的,而是通過各種手段挖過來的,這情況不再我今天要討論的范圍中。
技術(shù)學(xué)得明白不明白,人家?guī)讉€(gè)問題就把你的深淺問出來了,只要問一些具體的技術(shù)點(diǎn),就很容易看出你是真懂還是假懂,很容看出你的技術(shù)深度和實(shí)力,所以,技術(shù)是來不得半點(diǎn)虛假的,必須扎扎實(shí)實(shí)。
由于項(xiàng)目的種類繁多,涉及到現(xiàn)實(shí)生活中的各行各業(yè),什么五花八門的業(yè)務(wù)都有,例如,酒店房間預(yù)定管理,公司車輛調(diào)度管理,學(xué)校課程教室管理,超市進(jìn)銷存管理,知識(shí)內(nèi)容管理,等等……成千上萬等等,但是,不管是什么項(xiàng)目,采用的無非都是我們學(xué)習(xí)的那些目前流行和常用的技術(shù)。技術(shù)好、經(jīng)驗(yàn)豐富,則項(xiàng)目做出來的效率高些,程序更穩(wěn)定和更容易維護(hù)些;技術(shù)差點(diǎn),碰碰磕磕最后也能把項(xiàng)目做出來,無非是做的周期長(zhǎng)點(diǎn)、返工的次數(shù)多點(diǎn),程序代碼寫得差些,用的技術(shù)笨拙點(diǎn)。如果一個(gè)人不是完完全全做過某個(gè)項(xiàng)目,他是不太關(guān)心該項(xiàng)目的業(yè)務(wù)的,對(duì)其中的一些具體細(xì)節(jié)更是一竅不知,(如果我招你來做圖書管理,你項(xiàng)目經(jīng)歷說你做過汽車調(diào)度,那我能問你汽車調(diào)度具體怎么回事嗎?不會(huì),所以,你很容易蒙混過去的)而一個(gè)程序員的整個(gè)職業(yè)生涯中能實(shí)實(shí)在在和完完整整做出來的項(xiàng)目沒幾個(gè),更別說在多個(gè)不同行業(yè)的項(xiàng)目了,有的程序員更是一輩子都只是在做某一個(gè)行業(yè)的項(xiàng)目,結(jié)果他就成了這個(gè)行業(yè)的專家(專門干一件事的家伙)。所以,技術(shù)面試官通常沒正好親身經(jīng)歷過你簡(jiǎn)歷寫的那些項(xiàng)目,他不可能去問你寫的那些項(xiàng)目的具體細(xì)節(jié),而是只能泛泛地問你這個(gè)項(xiàng)目是多少人做的,做了多長(zhǎng)時(shí)間,開發(fā)的過程,你在做項(xiàng)目的過程中有什么心得和收獲,用的什么技術(shù)等面上的問題,所以,簡(jiǎn)歷上的項(xiàng)目經(jīng)歷可以含有很多水分,很容易作假,技術(shù)面試官也無法在項(xiàng)目上甄別你的真?zhèn)巍?/p>
簡(jiǎn)歷該怎么寫:精通那些技術(shù),有一些什么項(xiàng)目經(jīng)歷
教項(xiàng)目是為了鞏固和靈活整合運(yùn)用技術(shù),增強(qiáng)學(xué)習(xí)的趣味性,熟悉做項(xiàng)目的流程,或得一些專業(yè)課程中無法獲得的特有項(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í)的趣味性,但無法獲得實(shí)際的項(xiàng)目經(jīng)驗(yàn)。(項(xiàng)目主要是增加你經(jīng)驗(yàn)的可信度,獲得更多面試機(jī)會(huì),真正能不能找到工作,找到好工作,主要看你鍵盤上的功夫了)
建議大家盡量開自己的blog,堅(jiān)持每天寫技術(shù)blog。在簡(jiǎn)歷上寫上自己的blog地址,可以多轉(zhuǎn)載一些技術(shù)文章。
Java就業(yè)培訓(xùn)教程就是小沈陽
1.?Java基礎(chǔ)部分
基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語法,集合的語法,io?的語法,虛擬機(jī)方面的語法,其他
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來與一個(gè)整數(shù)進(jìn)行&運(yùn)算,來獲取該整數(shù)的最低4個(gè)bit位,例如,0x31?&?0x0f的結(jié)果為0x01。?
?
備注:這道題先說兩者的共同點(diǎn),再說出&&和&的特殊之處,并列舉一些經(jīng)典的例子來表明自己理解透徹深入、實(shí)際經(jīng)驗(yàn)豐富。?
3、Java有沒有g(shù)oto??
java中的保留字,現(xiàn)在沒有在java中使用。
?
4、在JAVA中,如何跳出當(dāng)前的多重嵌套循環(huán)??
在Java中,要想跳出多重循環(huán),可以在外面的循環(huán)語句前定義一個(gè)標(biāo)號(hào),然后在里層循環(huán)體的代碼中使用帶有標(biāo)號(hào)的break?語句,即可跳出外層循環(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的語法規(guī)定,并且不能被隱式轉(zhuǎn)換成int類型,所以,它們不能作用于swtich語句中。?
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語言規(guī)定的運(yùn)算符,java編譯器會(huì)對(duì)它進(jìn)行特殊處理,因此可以正確編譯。?
7、char型變量中能不能存貯一個(gè)中文漢字?為什么??
char型變量是用來存儲(chǔ)Unicode編碼的字符的,unicode編碼字符集中包含了漢字,所以,char型變量中當(dāng)然可以存儲(chǔ)漢字啦。不過,如果某個(gè)特殊的漢字沒有被包含在unicode編碼字符集中,那么,這個(gè)char型變量中就不能存儲(chǔ)這個(gè)特殊漢字。補(bǔ)充說明:unicode編碼占用兩個(gè)字節(jié),所以,char類型的變量也是占用兩個(gè)字節(jié)。
備注:后面一部分回答雖然不是在正面回答題目,但是,為了展現(xiàn)自己的學(xué)識(shí)和表現(xiàn)自己對(duì)問題理解的透徹深入,可以回答一些相關(guān)的知識(shí),做到知無不言,言無不盡。?
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é)來存儲(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)位后超過了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)位后超過了byte類型的存儲(chǔ)空間,所以進(jìn)位部分被舍棄,即最終的結(jié)果為00000000,也就是0,這樣的結(jié)果顯然不是我們期望的,這說明計(jì)算機(jī)中的算術(shù)運(yùn)算是會(huì)發(fā)生越界情況的,兩個(gè)數(shù)值的運(yùn)算結(jié)果不能超過計(jì)算機(jī)中的該類型的數(shù)值范圍。由于Java中涉及表達(dá)式運(yùn)算時(shí)的類型自動(dòng)提升,我們無法用byte類型來做演示這種問題和現(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)
{
?
}
?
}
備注:要想寫出這個(gè)類的完整代碼,是非常復(fù)雜的,如果有興趣的話,可以參看jdk中自帶的java.math.BigInteger類的源碼。面試的人也知道誰都不可能在短時(shí)間內(nèi)寫出這個(gè)類的完整代碼的,他要的是你是否有這方面的概念和意識(shí),他最重要的還是考查你的能力,所以,你不要因?yàn)樽约簾o法寫出完整的最終結(jié)果就放棄答這道題,你要做的就是你比別人寫得多,證明你比別人強(qiáng),你有這方面的思想意識(shí)就可以了,畢竟別人可能連題目的意思都看不懂,什么都沒寫,你要敢于答這道題,即使只答了一部分,那也與那些什么都不懂的人區(qū)別出來,拉開了距離,算是矮子中的高個(gè),機(jī)會(huì)當(dāng)然就屬于你了。另外,答案中的框架代碼也很重要,體現(xiàn)了一些面向?qū)ο笤O(shè)計(jì)的功底,特別是其中的方法命名很專業(yè),用的英文單詞很精準(zhǔn),這也是能力、經(jīng)驗(yàn)、專業(yè)性、英語水平等多個(gè)方面的體現(xiàn),會(huì)給人留下很好的印象,在編程能力和其他方面條件差不多的情況下,英語好除了可以使你獲得更多機(jī)會(huì)外,薪水可以高出一千元。?
?
10、使用final關(guān)鍵字修飾一個(gè)變量時(shí),是引用不能變,還是引用的對(duì)象不能變??
使用final關(guān)鍵字修飾一個(gè)變量時(shí),是指引用變量不能變,引用變量所指向的對(duì)象中的內(nèi)容還是可以改變的。例如,對(duì)于如下語句:
?final?StringBuffer?a=new?StringBuffer("immutable");
執(zhí)行如下語句將報(bào)告編譯期錯(cuò)誤:
a=new?StringBuffer("");
但是,執(zhí)行如下語句則可以通過編譯:
a.append("?broken!");?
?
有人在定義方法的參數(shù)時(shí),可能想采用如下形式來阻止方法內(nèi)部修改傳進(jìn)來的參數(shù)對(duì)象:
public?void?method(final??StringBuffer??param)
{
}?
實(shí)際上,這是辦不到的,在該方法內(nèi)部仍然可以增加如下代碼來修改參數(shù)對(duì)象:
param.append("a");
11、"=="和equals方法究竟有什么區(qū)別?
(單獨(dú)把一個(gè)東西說清楚,然后再說清楚另一個(gè),這樣,它們的區(qū)別自然就出來了,混在一起說,則很難說清楚)
==操作符專門用來比較兩個(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ū)ο箢愋偷淖兞?#xff0c;如果要比較兩個(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語句創(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í)際開發(fā)中,我們經(jīng)常要比較傳遞進(jìn)來的字符串內(nèi)容是否等,例如,String?input?=?…;input.equals(“quit”),許多人稍不注意就使用==進(jìn)行比較了,這是錯(cuò)誤的,隨便從網(wǎng)上找?guī)讉€(gè)項(xiàng)目實(shí)戰(zhàn)的教學(xué)視頻看看,里面就有大量這樣的錯(cuò)誤。記住,字符串的比較基本上都是使用equals方法。
如果一個(gè)類沒有自己定義equals方法,那么它將繼承Object類的equals方法,Object類的equals方法的實(shí)現(xiàn)代碼如下:
boolean?equals(Object?o){
return?this==o;
}
這說明,如果一個(gè)類沒有自己定義equals方法,它默認(rèn)的equals方法(從Object?類繼承的)就是使用==操作符,也是在比較兩個(gè)變量指向的對(duì)象是否是同一對(duì)象,這時(shí)候使用equals和使用==會(huì)得到同樣的結(jié)果,如果比較的是兩個(gè)獨(dú)立的對(duì)象則總返回false。如果你編寫的類希望能夠比較該類創(chuàng)建的兩個(gè)實(shí)例對(duì)象的內(nèi)容是否相同,那么你必須覆蓋equals方法,由你自己寫代碼來決定在什么情況即可認(rèn)為兩個(gè)對(duì)象的內(nèi)容是相同的。
12、靜態(tài)變量和實(shí)例變量的區(qū)別??
在語法定義上的區(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ì)象后才可以通過這個(gè)對(duì)象來使用,靜態(tài)變量則可以直接使用類名來引用。
例如,對(duì)于下面的程序,無論創(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è)解答除了說清楚兩者的區(qū)別外,最后還用一個(gè)具體的應(yīng)用例子來說明兩者的差異,體現(xiàn)了自己有很好的解說問題和設(shè)計(jì)案例的能力,思維敏捷,超過一般程序員,有寫作能力!
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)用。也就是說,當(dāng)一個(gè)static方法被調(diào)用時(shí),可能還沒有創(chuàng)建任何實(shí)例對(duì)象,如果從一個(gè)static方法中發(fā)出對(duì)非static方法的調(diào)用,那個(gè)非static方法是關(guān)聯(lián)到哪個(gè)對(duì)象上的呢?這個(gè)邏輯無法成立,所以,一個(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則無法表達(dá)出未賦值的情況,例如,要想表達(dá)出沒有參加考試和考試成績(jī)?yōu)?的區(qū)別,則只能使用Integer。在JSP開發(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),即將原來的數(shù)字加上0.5后再向下取整,所以,Math.round(11.5)的結(jié)果為12,Math.round(-11.5)的結(jié)果為-11。
16、作用域public,private,protected,以及不寫時(shí)的區(qū)別
這四個(gè)作用域的可見范圍如下表所示。
說明:如果在修飾的元素上面沒有寫任何訪問修飾符,則表示friendly。
?
作用域????當(dāng)前類?同一package?子孫類?其他package?
public????√?????√??????????√???????√?
protected??√?????√??????????√??????×?
friendly???√?????√??????????×??????×?
private????√?????×??????????×??????×?
備注:只要記住了有4種訪問權(quán)限,4個(gè)訪問范圍,然后將全選和范圍在水平和垂直方向上分別按排從小到大或從大到小的順序排列,就很容易畫出上面的圖了。
17、Overload和Override的區(qū)別。Overloaded的方法是否可以改變返回值的類型??
Overload是重載的意思,Override是覆蓋的意思,也就是重寫。
重載Overload表示同一個(gè)類中可以有多個(gè)名稱相同的方法,但這些方法的參數(shù)列表各不相同(即參數(shù)個(gè)數(shù)或類型不同)。
重寫Override表示子類中的方法可以與父類中的某個(gè)方法的名稱和參數(shù)完全相同,通過子類創(chuàng)建的實(shí)例對(duì)象調(diào)用這個(gè)方法時(shí),將調(diào)用子類中的定義方法,這相當(dāng)于把父類中定義的那個(gè)完全相同的方法給覆蓋了,這也是面向?qū)ο缶幊痰亩鄳B(tài)性的一種表現(xiàn)。子類覆蓋父類的方法時(shí),只能比父類拋出更少的異常,或者是拋出父類拋出的異常的子異常,因?yàn)樽宇惪梢越鉀Q父類的一些問題,不能比父類有更多的問題。子類方法的訪問權(quán)限只能比父類的更大,不能更小。
至于Overloaded的方法是否可以改變返回值的類型這個(gè)問題,要看你倒底想問什么呢?這個(gè)題目很模糊。如果幾個(gè)Overloaded的方法的參數(shù)列表不一樣,它們的返回者類型當(dāng)然也可以不一樣。但我估計(jì)你想問的問題是:如果兩個(gè)方法的參數(shù)列表完全一樣,是否可以讓它們的返回值不同來實(shí)現(xiàn)重載Override。這是不行的,我們可以用反證法來說明這個(gè)問題,因?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就無法確定編程者倒底是想調(diào)用哪個(gè)方法了,因?yàn)樗鼰o法通過返回結(jié)果類型來判斷。?
?
18、構(gòu)造器Constructor是否可被override??
構(gòu)造器Constructor不能被繼承,因此不能重寫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ì)和作用,這些問題都很好回答,你想想,如果你是java語言的設(shè)計(jì)者,你是否會(huì)提供這樣的支持,如果不提供的話,有什么理由嗎?如果你沒有道理不提供,那答案就是肯定的了。
?
20、寫clone()方法時(shí),通常都有一行代碼,是什么??
clone?有缺省行為,super.clone();因?yàn)槭紫纫迅割愔械某蓡T復(fù)制到位,然后才是復(fù)制自己的成員。?
21、面向?qū)ο蟮奶卣饔心男┓矫?/h3>
計(jì)算機(jī)軟件系統(tǒng)是現(xiàn)實(shí)生活中的業(yè)務(wù)在計(jì)算機(jī)中的映射,而現(xiàn)實(shí)生活中的業(yè)務(wù)其實(shí)就是一個(gè)個(gè)對(duì)象協(xié)作的過程。面向?qū)ο缶幊叹褪前船F(xiàn)實(shí)業(yè)務(wù)一樣的方式將程序代碼按一個(gè)個(gè)對(duì)象進(jìn)行組織和編寫,讓計(jì)算機(jī)系統(tǒng)能夠識(shí)別和理解用對(duì)象方式組織和編寫的程序代碼,這樣就可以把現(xiàn)實(shí)生活中的業(yè)務(wù)對(duì)象映射到計(jì)算機(jī)系統(tǒng)中。
面向?qū)ο蟮木幊陶Z言有封裝、繼承?、抽象、多態(tài)等4個(gè)主要的特征。
1封裝:
封裝是保證軟件部件具有優(yōu)良的模塊性的基礎(chǔ),封裝的目標(biāo)就是要實(shí)現(xiàn)軟件部件的“高內(nèi)聚、低耦合”,防止程序相互依賴性而帶來的變動(dòng)影響。在面向?qū)ο蟮木幊陶Z言中,對(duì)象是封裝的最基本單位,面向?qū)ο蟮姆庋b比傳統(tǒng)語言的封裝更為清晰、更為有力。面向?qū)ο蟮姆庋b就是把描述一個(gè)對(duì)象的屬性和行為的代碼封裝在一個(gè)“模塊”中,也就是一個(gè)類中,屬性用變量定義,行為用方法進(jìn)行定義,方法可以直接訪問同一個(gè)對(duì)象中的屬性。通常情況下,只要記住讓變量和訪問這個(gè)變量的方法放在一起,將一個(gè)類中的成員變量全部定義成私有的,只有這個(gè)類自己的方法才可以訪問到這些成員變量,這就基本上實(shí)現(xiàn)對(duì)象的封裝,就很容易找出要分配到這個(gè)類上的方法了,就基本上算是會(huì)面向?qū)ο蟮木幊塘恕?/p>
例如,人要在黑板上畫圓,這一共涉及三個(gè)對(duì)象:人、黑板、圓,畫圓的方法要分配給哪個(gè)對(duì)象呢?由于畫圓需要使用到圓心和半徑,圓心和半徑顯然是圓的屬性,如果將它們?cè)陬愔卸x成了私有的成員變量,那么,畫圓的方法必須分配給圓,它才能訪問到圓心和半徑這兩個(gè)屬性,人以后只是調(diào)用圓的畫圓方法、表示給圓發(fā)給消息而已,畫圓這個(gè)方法不應(yīng)該分配在人這個(gè)對(duì)象上,這就是面向?qū)ο蟮姆庋b性,即將對(duì)象封裝成一個(gè)高度自治和相對(duì)封閉的個(gè)體,對(duì)象狀態(tài)(屬性)由這個(gè)對(duì)象自己的行為(方法)來讀取和改變。一個(gè)更便于理解的例子就是,司機(jī)將火車剎住了,剎車的動(dòng)作是分配給司機(jī),還是分配給火車,顯然,應(yīng)該分配給火車,因?yàn)樗緳C(jī)自身是不可能有那么大的力氣將一個(gè)火車給停下來的,只有火車自己才能完成這一動(dòng)作,火車需要調(diào)用內(nèi)部的離合器和剎車片等多個(gè)器件協(xié)作才能完成剎車這個(gè)動(dòng)作,司機(jī)剎車的過程只是給火車發(fā)了一個(gè)消息,通知火車要執(zhí)行剎車動(dòng)作而已。
?
抽象:
抽象就是找出一些事物的相似和共性之處,然后將這些事物歸為一個(gè)類,這個(gè)類只考慮這些事物的相似和共性之處,并且會(huì)忽略與當(dāng)前主題和目標(biāo)無關(guān)的那些方面,將注意力集中在與當(dāng)前目標(biāo)有關(guān)的方面。抽象包括行為抽象和狀態(tài)抽象兩個(gè)方面。例如,定義一個(gè)Person類,如下:
class?Person
{
String?name;
int?age;
}
人本來是很復(fù)雜的事物,有很多方面,但因?yàn)楫?dāng)前系統(tǒng)只需要了解人的姓名和年齡,所以上面定義的類中只包含姓名和年齡這兩個(gè)屬性,這就是一種抽像,使用抽象可以避免考慮一些與目標(biāo)無關(guān)的細(xì)節(jié)。我對(duì)抽象的理解就是不要用顯微鏡去看一個(gè)事物的所有方面,這樣涉及的內(nèi)容就太多了,而是要善于劃分問題的邊界,當(dāng)前系統(tǒng)需要什么,就只考慮什么。
?
繼承:
在定義和實(shí)現(xiàn)一個(gè)類的時(shí)候,可以在一個(gè)已經(jīng)存在的類的基礎(chǔ)之上來進(jìn)行,把這個(gè)已經(jīng)存在的類所定義的內(nèi)容作為自己的內(nèi)容,并可以加入若干新的內(nèi)容,或修改原來的方法使之更適合特殊的需要,這就是繼承。繼承是子類自動(dòng)共享父類數(shù)據(jù)和方法的機(jī)制,這是類之間的一種關(guān)系,提高了軟件的可重用性和可擴(kuò)展性。
?
多態(tài):
多態(tài)是指程序中定義的引用變量所指向的具體類型和通過該引用變量發(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)方法。如果的子類沒有實(shí)現(xiàn)抽象父類中的所有抽象方法,那么子類也必須定義為abstract類型。
接口(interface)可以說成是抽象類的一種特例,接口中的所有方法都必須是抽象的。接口?中的方法定義默認(rèn)為public?abstract類型,接口中的成員變量類型默認(rèn)為public?static?final。
下面比較一下兩者的語法區(qū)別:
1.抽象類可以有構(gòu)造方法,接口中不能有構(gòu)造方法。
2.抽象類中可以有普通成員變量,接口中沒有普通成員變量
3.抽象類中可以包含非抽象的普通方法,接口中的所有方法必須都是抽象的,不能有非抽象的普通方法。
4.?抽象類中的抽象方法的訪問類型可以是public,protected和默認(rèn)類型,但接口中的抽象方法只能是public類型的,并且默認(rèn)即為public?abstract類型。
5.?抽象類中可以包含靜態(tài)方法,接口中不能包含靜態(tài)方法
6.?抽象類和接口中都可以包含靜態(tài)成員變量,抽象類中的靜態(tài)成員變量的訪問類型可以任意,但接口中定義的變量只能是public?static類型,并且默認(rèn)即為public?static類型。
7.?一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,但只能繼承一個(gè)抽象類。
下面接著再說說兩者在應(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)限判斷、記錄訪問日志和處理異常,那么就可以定義一個(gè)抽象的基類,讓所有的Servlet都繼承這個(gè)抽象基類,在抽象基類的service方法中完成權(quán)限判斷、記錄訪問日志和處理異常的代碼,在各個(gè)子類中只是完成各自的業(yè)務(wù)邏輯代碼,偽代碼如下:
public?abstract?class?BaseServlet?extends?HttpServlet
{
public?void?service(HttpServletRequest?request,?HttpServletResponse?response)?throws?IOExcetion,ServletException
{
記錄訪問日志
進(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;??
//注意訪問權(quán)限定義成protected,顯得既專業(yè),又嚴(yán)謹(jǐn),因?yàn)樗菍iT給子類用的
}
?
public?class?MyServlet1?extends?BaseServlet
{
protected?void?doService(HttpServletRequest?request,?HttpServletResponse?response)?throws?IOExcetion,ServletException
{
本Servlet只處理的具體業(yè)務(wù)邏輯代碼
}?
?
}
父類方法中間的某段代碼不確定,留給子類干,就用模板方法設(shè)計(jì)模式。
備注:這道題的思路是先從總體解釋抽象類和接口的基本概念,然后再比較兩者的語法細(xì)節(jié),最后再說兩者的應(yīng)用區(qū)別。比較兩者語法細(xì)節(jié)區(qū)別的條理是:先從一個(gè)類中的構(gòu)造方法、普通成員變量和方法(包括抽象方法),靜態(tài)變量和方法,繼承性等6個(gè)方面逐一去比較回答,接著從第三者繼承的角度的回答,特別是最后用了一個(gè)典型的例子來展現(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)的編程語言實(shí)現(xiàn)的,不存在著被子類實(shí)現(xiàn)的問題,所以,它也不能是抽象的,不能與abstract混用。例如,FileOutputSteam類要硬件打交道,底層的實(shí)現(xiàn)用的是操作系統(tǒng)相關(guān)的api實(shí)現(xiàn),例如,在windows用c語言實(shí)現(xiàn)的,所以,查看jdk?的源代碼,可以發(fā)現(xiàn)FileOutputStream的open方法的定義如下:
private?native?void?open(String?name)?throws?FileNotFoundException;
如果我們要用java調(diào)用別人寫的c語言函數(shù),我們是無法直接調(diào)用的,我們需要按照java的要求寫一個(gè)c語言的函數(shù),又我們的這個(gè)c語言函數(shù)去調(diào)用別人的c語言函數(shù)。由于我們的c語言函數(shù)是按java的要求來寫的,我們這個(gè)c語言函數(shù)就可以與java對(duì)接上,java那邊的對(duì)接方式就是定義出與我們這個(gè)c函數(shù)相對(duì)應(yīng)的方法,java中對(duì)應(yīng)的方法不需要寫具體的代碼,但需要在前面聲明native。
關(guān)于synchronized與abstract合用的問題,我覺得也不行,因?yàn)樵谖規(guī)啄甑膶W(xué)習(xí)和開發(fā)中,從來沒見到過這種情況,并且我覺得synchronized應(yīng)該是作用在一個(gè)具體的方法上才有意義。?
25、什么是內(nèi)部類?
內(nèi)部類就是在一個(gè)類的內(nèi)部定義的類,內(nèi)部類中不能定義靜態(tài)成員(我想可能是既然靜態(tài)成員類似c語言的全局變量,而內(nèi)部類通常是用于創(chuàng)建內(nèi)部對(duì)象用的,所以,把“全局變量”放在內(nèi)部類中就是毫無意義的事情,既然是毫無意義的事情,就應(yīng)該被禁止),內(nèi)部類可以直接訪問外部類中的成員變量,內(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)部類的訪問類型可以是public,protecte,默認(rèn)的,private等4種類型,這就好像類中定義的成員變量有4種訪問類型一樣,它們決定這個(gè)內(nèi)部類的定義對(duì)其他類是否可見;對(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)部類前面不能有訪問類型修飾符,就好像方法中定義的局部變量一樣,但這種內(nèi)部類的前面可以使用final或abstract修飾符。這種內(nèi)部類對(duì)其他類是不可見的其他類無法引用這種內(nèi)部類,但是這種內(nèi)部類創(chuàng)建的實(shí)例對(duì)象可以傳遞給其他類訪問。這種內(nèi)部類必須是先定義,后使用,即內(nèi)部類的定義代碼必須出現(xiàn)在使用該類之前,這與方法中的局部變量必須先定義后使用的道理也是一樣的。這種內(nèi)部類可以訪問方法體中的局部變量,但是,該局部變量前必須加final修飾符。
對(duì)于這些細(xì)節(jié),只要在eclipse寫代碼試試,根據(jù)開發(fā)工具提示的各類錯(cuò)誤信息就可以馬上了解到。
在方法外部定義的內(nèi)部類前面可以加上static關(guān)鍵字,從而成為靜態(tài)內(nèi)部類,或者叫Static?Nested?Class。Static?Nested?Class與普通類在運(yùn)行時(shí)的行為和功能上沒有什么區(qū)別,只是在編程引用時(shí)的語法上有一些差別,它可以定義成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,那么可以使用如下語句創(chuàng)建Inner類:
Outer.Inner?inner?=?new?Outer.Inner();
由于static?Nested?Class不依賴于外部類的實(shí)例對(duì)象,所以,static?Nested?Class能訪問外部類的非static成員變量。當(dāng)在外部類中訪問Static?Nested?Class時(shí),可以直接使用Static?Nested?Class的名字,而不需要加上外部類的名字了,在Static?Nested?Class中也可以直接引用外部類的static的成員變量,不需要加上外部類的名字。
?
最后,在方法體內(nèi)部還可以采用如下語法來創(chuàng)建一種匿名內(nèi)部類,即定義某一接口或類的子類的同時(shí),還創(chuàng)建了該子類的實(shí)例對(duì)象,無需為該子類定義名稱:
public?class?Outer
{
public?void?start()
{
new?Thread(
new?Runable(){
public?void?run(){};
}
).start();
}
}
?
備注:首先根據(jù)你的印象說出你對(duì)內(nèi)部類的總體方面的特點(diǎn):例如,在兩個(gè)地方可以定義,可以訪問外部類的成員變量,不能定義靜態(tài)成員,這是大的特點(diǎn)。然后再說一些細(xì)節(jié)方面的知識(shí),例如,幾種定義方式的語法區(qū)別,靜態(tài)內(nèi)部類,以及匿名內(nèi)部類。
26、內(nèi)部類可以引用他包含類的成員嗎?有沒有什么限制??
完全可以。如果不是靜態(tài)內(nèi)部類,那沒有什么限制!?
如果你把靜態(tài)嵌套類當(dāng)作內(nèi)部類的一種特例,那在這種情況下不可以訪問外部類的普通成員變量,而只能訪問外部類中的靜態(tài)成員,例如,下面的代碼:
class?Outer
{
static?int?x;
static?class?Inner
{
void?test()
{
syso(x);
}
}
}
如果問靜態(tài)內(nèi)部類能否訪問外部類的成員這個(gè)問題,該如何回答:
答題時(shí),也要能察言觀色,揣摩提問者的心思,顯然人家希望你說的是靜態(tài)內(nèi)部類不能訪問外部類的成員,但你一上來就頂牛,這不好,要先順著人家,讓人家滿意,然后再說特殊情況,讓人家吃驚。
?
27、Static?Nested?Class?和?Inner?Class的不同。?
參見前面的什么是內(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)容到底變了沒有?
沒有。因?yàn)镾tring被設(shè)計(jì)成不可變(immutable)類,所以它的所有對(duì)象都是不可變對(duì)象。在這段代碼中,s原先指向一個(gè)String對(duì)象,內(nèi)容是?"Hello",然后我們對(duì)s進(jìn)行了+操作,那么s所指向的那個(gè)對(duì)象是否發(fā)生了改變呢?答案是沒有。這時(shí),s不指向原來那個(gè)對(duì)象了,而指向了另一個(gè)?String對(duì)象,內(nèi)容為"Hello?world!",原來那個(gè)對(duì)象還存在于內(nèi)存之中,只是s這個(gè)引用變量不再指向它了。
通過上面的說明,我們很容易導(dǎo)出另一個(gè)結(jié)論,如果經(jīng)常對(duì)字符串進(jìn)行各種各樣的修改,或者說,不可預(yù)見的修改,那么使用String來代表字符串的話會(huì)引起很大的內(nèi)存開銷。因?yàn)?String對(duì)象建立之后不能再改變,所以對(duì)于每一個(gè)不同的字符串,都需要一個(gè)String對(duì)象來表示。這時(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)存開銷大,并且沒有意義,因?yàn)镾tring對(duì)象不可改變,所以對(duì)于內(nèi)容相同的字符串,只要一個(gè)String對(duì)象來表示就可以了。也就說,多次調(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ì)象,無論內(nèi)容是否相同。
至于為什么要把String類設(shè)計(jì)成不可變類,是它的用途決定的。其實(shí)不只String,很多Java標(biāo)準(zhǔn)類庫中的類都是不可變的。在開發(fā)一個(gè)系統(tǒng)的時(shí)候,我們有時(shí)候也需要設(shè)計(jì)不可變類,來傳遞一組相關(guān)的值,這也是面向?qū)ο笏枷氲捏w現(xiàn)。不可變類有一些優(yōu)點(diǎn),比如因?yàn)樗膶?duì)象是只讀的,所以多線程并發(fā)訪問也不會(huì)有任何問題。當(dāng)然也有一些缺點(diǎn),比如每個(gè)不同的狀態(tài)都要一個(gè)對(duì)象來代表,可能會(huì)造成性能上的問題。所以Java標(biāo)準(zhǔn)類庫還提供了一個(gè)可變版本,即?StringBuffer。
31、是否可以繼承String類??
String類是final類故不可以繼承。?
?
32、String?s?=?new?String("xyz");創(chuàng)建了幾個(gè)String?Object??二者之間有什么區(qū)別?
兩個(gè),一個(gè)放在常量區(qū),不管寫多少遍,都是同一個(gè)。New?String每寫一遍,就創(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來動(dòng)態(tài)構(gòu)造字符數(shù)據(jù)。另外,String實(shí)現(xiàn)了equals方法,new?String(“abc”).equals(new?String(“abc”)的結(jié)果為true,而StringBuffer沒有實(shí)現(xiàn)equals方法,所以,new?StringBuffer(“abc”).equals(new?StringBuffer(“abc”)的結(jié)果為false。
?
接著要舉一個(gè)具體的例子來說明,我們要把1到100的所有數(shù)字拼起來,組成一個(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,我很難寫出來!我可以說說我的思路:
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ù)組有沒有l(wèi)ength()這個(gè)方法??String有沒有l(wèi)ength()這個(gè)方法??
數(shù)組沒有l(wèi)ength()這個(gè)方法,有l(wèi)ength的屬性。String有有l(wèi)ength()這個(gè)方法。
?
36、try?{}里有一個(gè)return語句,那么緊跟在這個(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。
我可以通過下面一個(gè)例子程序來幫助我解釋這個(gè)答案,從下面例子的運(yùn)行結(jié)果中可以發(fā)現(xiàn),try中的return語句調(diào)用的函數(shù)先于finally中調(diào)用的函數(shù)執(zhí)行,也就是說return語句先執(zhí)行,finally語句后執(zhí)行,所以,返回的結(jié)果是2。Return并不是讓函數(shù)馬上返回,而是return語句執(zhí)行后,將把返回結(jié)果放置進(jìn)函數(shù)棧中,此時(shí)函數(shù)并不是馬上返回,它要執(zhí)行finally語句后才真正開始返回。
在講解答案時(shí)可以用下面的程序來幫助分析:
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語句后執(zhí)行
?
38、final,?finally,?finalize的區(qū)別。?
final?用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。?
內(nèi)部類要訪問局部變量,局部變量必須定義成final類型,例如,一段代碼……
?
finally是異常處理語句結(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)行過程中可能出現(xiàn)的非正常狀態(tài),運(yùn)行時(shí)異常表示虛擬機(jī)的通常操作中可能遇到的異常,是一種常見運(yùn)行錯(cuò)誤。java編譯器要求方法必須聲明拋出可能發(fā)生的非運(yùn)行時(shí)異常,但是并不要求必須聲明拋出未被捕獲的運(yùn)行時(shí)異常。
40、error和exception有什么區(qū)別??
error?表示恢復(fù)不是不可能但很困難的情況下的一種嚴(yán)重問題。比如說內(nèi)存溢出。不可能指望程序能處理這樣的情況。?exception?表示一種設(shè)計(jì)或?qū)崿F(xiàn)問題。也就是說,它表示如果程序運(yùn)行正常,從不會(huì)發(fā)生的情況。?
?
41、Java中的異常處理機(jī)制的簡(jiǎn)單原理和應(yīng)用。?
當(dāng)JAVA程序違反了JAVA的語義規(guī)則時(shí),JAVA虛擬機(jī)就會(huì)將發(fā)生的錯(cuò)誤表示為一個(gè)異常。違反語義規(guī)則包括2種情況。一種是JAVA類庫內(nèi)置的語義檢查。例如數(shù)組下標(biāo)越界,會(huì)引發(fā)IndexOutOfBoundsException;訪問null的對(duì)象時(shí)會(huì)引發(fā)NullPointerException。另一種情況就是JAVA允許程序員擴(kuò)展這種語義檢查,程序員可以創(chuàng)建自己的異常,并自由選擇在何時(shí)用throw關(guān)鍵字引發(fā)異常。所有的異常都是java.lang.Thowable的子類。?
?
?
42、給我一個(gè)你最常見到的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語言如何進(jìn)行異常處理,關(guān)鍵字:throws,throw,try,catch,finally分別代表什么意義?在try塊中可以拋出異常嗎??
Java通過面向?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的異常處理是通過5個(gè)關(guān)鍵詞來實(shí)現(xiàn)的:try、catch、throw、throws和finally。一般情況下是用try來執(zhí)行一段程序,如果出現(xiàn)異常,系統(tǒng)會(huì)拋出(throws)一個(gè)異常,這時(shí)候你可以通過它的類型來捕捉(catch)它,或最后(finally)由缺省處理器來處理。?
用try來指定一塊預(yù)防所有"異常"的程序。緊跟在try程序后面,應(yīng)包含一個(gè)catch子句來指定你想要捕捉的"異常"的類型。?
throw語句用來明確地拋出一個(gè)"異常"。?
throws用來標(biāo)明一個(gè)成員函數(shù)可能拋出的各種"異常"。?
Finally為確保一段代碼不管發(fā)生什么"異常"都被執(zhí)行一段代碼。?
可以在一個(gè)成員函數(shù)調(diào)用的外面寫一個(gè)try語句,在這個(gè)成員函數(shù)內(nèi)部寫另一個(gè)try語句保護(hù)其他代碼。每當(dāng)遇到一個(gè)try語句,"異常"的框架就放到堆棧上面,直到所有的try語句都完成。如果下一級(jí)的try語句沒有對(duì)某種"異常"進(jìn)行處理,堆棧就會(huì)展開,直到遇到有處理這種"異常"的try語句。
?
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)樗话踩?/span>它會(huì)解除由線程獲取的所有鎖定,而且如果對(duì)象處于一種不連貫狀態(tài),那么其他線程能在那種狀態(tài)下檢查和修改它們。結(jié)果很難檢查出真正的問題所在。suspend()方法容易發(fā)生死鎖。調(diào)用suspend()的時(shí)候,目標(biāo)線程會(huì)停下來,但卻仍然持有在這之前獲得的鎖定。此時(shí),其他任何線程都不能訪問鎖定的資源,除非被"掛起"的線程恢復(fù)運(yùn)行。對(duì)任何線程來說,如果它們想恢復(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í)間過后,cpu才會(huì)回到這個(gè)線程上繼續(xù)往下執(zhí)行,如果當(dāng)前線程進(jìn)入了同步鎖,sleep方法并不會(huì)釋放鎖,即使當(dāng)前線程使用sleep方法讓出了cpu,但其他被同步鎖擋住了的線程也無法得到執(zhí)行。wait是指在一個(gè)已經(jīng)進(jìn)入了同步鎖的線程內(nèi),讓自己暫時(shí)讓出同步鎖,以便其他正在等待此鎖的線程可以得到同步鎖并運(yùn)行,只有其他線程調(diào)用了notify方法(notify并不釋放鎖,只是告訴調(diào)用過wait方法的線程可以去參與獲得鎖的競(jìng)爭(zhēng)了,但不是馬上得到鎖,因?yàn)殒i還在別人手里,別人還沒釋放。如果notify方法后面的代碼還有很多,需要這些代碼執(zhí)行完后才會(huì)釋放鎖,可以在notfiy方法后增加一個(gè)等待和一些代碼,看看效果),調(diào)用wait方法的線程就會(huì)解除wait狀態(tài)和程序可以再次得到鎖后繼續(xù)向下運(yùn)行。對(duì)于wait的講解一定要配合例子代碼來說明,才顯得自己真明白。
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?{
//釋放鎖有兩種方式,第一種方式是程序自然離開監(jiān)視器的范圍,也就是離開了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沒有釋放鎖,所以Thread1無法得不到鎖。
?
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、同步和異步有何異同,在什么情況下分別使用他們?舉例說明。?
如果數(shù)據(jù)將在線程間共享。例如正在寫的數(shù)據(jù)以后可能被另一個(gè)線程讀到,或者正在讀的數(shù)據(jù)可能已經(jīng)被另一個(gè)線程寫過了,那么這些數(shù)據(jù)就是共享數(shù)據(jù),必須進(jìn)行同步存取。?
當(dāng)應(yīng)用程序在對(duì)象上調(diào)用了一個(gè)需要花費(fèi)很長(zhǎng)時(shí)間來執(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)鍵字,如果沒加,則能。
??????2.如果這個(gè)方法內(nèi)部調(diào)用了wait,則可以進(jìn)入其他synchronized方法。
????3.如果其他個(gè)方法都加了synchronized關(guān)鍵字,并且內(nè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í)行多段程序呢?這是從宏觀上來看的,cpu一會(huì)執(zhí)行a線索,一會(huì)執(zhí)行b線索,切換時(shí)間很快,給人的感覺是a,b在同時(shí)執(zhí)行,好比大家在同一個(gè)辦公室上網(wǎng),只有一條鏈接到外部網(wǎng)線,其實(shí),這條網(wǎng)線一會(huì)為a傳數(shù)據(jù),一會(huì)為b傳數(shù)據(jù),由于切換時(shí)間很短暫,所以,大家感覺都在同時(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語句時(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更精確的線程語義和更好的性能。synchronized會(huì)自動(dòng)釋放鎖,而Lock一定要求程序員手工釋放,并且必須在finally從句中釋放。Lock還有更強(qiáng)大的功能,例如,它的tryLock方法可以非阻塞方式去拿鎖。?
舉例說明(對(duì)下面的題用lock進(jìn)行了改寫):
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。寫出程序。?
以下程序使用內(nèi)部類實(shí)現(xiàn)線程,對(duì)j增減的時(shí)候沒有考慮順序問題。?
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ù)的元素(本來題目問的與hashset沒有任何關(guān)系,但為了說清楚ArrayList與Vector的功能,我們使用對(duì)比方式,更有利于說明問題)。
?
接著才說ArrayList與Vector的區(qū)別,這主要包括兩個(gè)方面:.?
(1)同步性:
Vector是線程安全的,也就是說是它的方法之間是線程同步的,而ArrayList是線程序不安全的,它的方法之間是線程不同步的。如果只有一個(gè)線程會(huì)訪問到集合,那最好是使用ArrayList,因?yàn)樗豢紤]線程安全,效率會(huì)高些;如果有多個(gè)線程會(huì)訪問到集合,那最好是使用Vector,因?yàn)椴恍枰覀冏约涸偃タ紤]和編寫線程安全的代碼。
(2)數(shù)據(jù)增長(zhǎng):
ArrayList與Vector都有一個(gè)初始的容量大小,當(dāng)存儲(chǔ)進(jìn)它們里面的元素的個(gè)數(shù)超過了容量時(shí),就需要增加ArrayList與Vector的存儲(chǔ)空間,每次要增加存儲(chǔ)空間時(shí),不是只增加一個(gè)存儲(chǔ)單元,而是增加多個(gè)存儲(chǔ)單元,每次增加的存儲(chǔ)單元的個(gè)數(shù)在內(nèi)存空間利用與程序效率之間要取得一定的平衡。Vector默認(rèn)增長(zhǎng)為原來兩倍,而ArrayList的增長(zhǎng)策略在文檔中沒有明確規(guī)定(從源代碼看到的是增長(zhǎng)為原來的1.5倍)。ArrayList與Vector都可以設(shè)置初始的空間大小,Vector還可以設(shè)置增長(zhǎng)的空間大小,而ArrayList沒有提供設(shè)置增長(zhǎng)空間的方法。
54、HashMap和Hashtable的區(qū)別
(條理上還需要整理,也是先說相同點(diǎn),再說不同點(diǎn))
HashMap是Hashtable的輕量級(jí)實(shí)現(xiàn)(非線程安全的實(shí)現(xiàn)),他們都完成了Map接口,主要區(qū)別在于HashMap允許空(null)鍵值(key),由于非線程安全,在只有一個(gè)線程訪問的情況下,效率要高于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è)線程訪問Hashtable時(shí),不需要自己為它的方法實(shí)現(xiàn)同步,而HashMap?就必須為之提供外同步。?
Hashtable和HashMap采用的hash/rehash算法都大概一樣,所以性能不會(huì)有很大的差異。
?
就HashMap與HashTable主要從三方面來說。?
一.歷史原因:Hashtable是基于陳舊的Dictionary類的,HashMap是Java?1.2引進(jìn)的Map接口的一個(gè)實(shí)現(xiàn)?
二.同步性:Hashtable是線程安全的,也就是說是同步的,而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ù)是沒有順序的,其鍵是不能重復(fù)的,它的值是可以有重復(fù)的。
56、List,?Set,?Map是否繼承自Collection接口??
???List,Set是,Map不是?
?
57、List、Map、Set三個(gè)接口,存取元素時(shí),各有什么特點(diǎn)??
List?以特定次序來持有元素,可有重復(fù)元素。Set?無法擁有重復(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,這些問題感謝以前一個(gè)叫崔健的學(xué)員提出,最后通過查看源代碼給他解釋清楚,看本次培訓(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、說出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ì)列來使用。
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ù)的,那么用什么方法來區(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ù)值索引訪問元素的情形。?
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)?#xff0c;我只要在eclispe下按點(diǎn)操作符,很自然的這些方法就出來了。我記住的一些思想就是List類會(huì)有g(shù)et(int?index)這樣的方法,因?yàn)樗梢园错樞蛉≡?#xff0c;而set類中沒有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沒有什么關(guān)系了,這時(shí)候hashcode不等是可以的,例如arrayList存儲(chǔ)的對(duì)象就不用實(shí)現(xiàn)hashcode,當(dāng)然,我們沒有理由不實(shí)現(xiàn),通常都會(huì)去實(shí)現(xiàn)的。
?
64、java中有幾種類型的流?JDK為每種類型的流提供了一些抽象類以供繼承,請(qǐng)說出他們分別是哪些類??
字節(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ǔ)到硬盤或者傳送給網(wǎng)絡(luò)上的其他計(jì)算機(jī),這個(gè)過程我們可以自己寫代碼去把一個(gè)java對(duì)象變成某個(gè)格式的字節(jié)流再傳輸,但是,jre本身就提供了這種支持,我們可以調(diào)用OutputStream的writeObject方法來做,如果要讓java?幫我們做,要被傳輸?shù)膶?duì)象必須實(shí)現(xiàn)serializable接口,這樣,javac編譯時(shí)就會(huì)進(jìn)行特殊處理,編譯的類才可以被writeObject方法操作,這就是所謂的序列化。需要被序列化的類必須實(shí)現(xiàn)Serializable接口,該接口是一個(gè)mini接口,其中沒有需要實(shí)現(xiàn)的方法,implements?Serializable只是為了標(biāo)注該對(duì)象是可被序列化的。?
?
?
例如,在web開發(fā)中,如果對(duì)象被保存在了Session中,tomcat在重啟時(shí)要把Session對(duì)象序列化到硬盤,這個(gè)對(duì)象就必須實(shí)現(xiàn)Serializable接口。如果對(duì)象要經(jīng)過分布式系統(tǒng)進(jìn)行網(wǎng)絡(luò)傳輸或通過rmi等遠(yuǎn)程調(diào)用,這就需要在網(wǎng)絡(luò)上傳輸對(duì)象,被傳輸?shù)膶?duì)象就必須實(shí)現(xiàn)Serializable接口。
?
66、描述一下JVM加載class文件的原理機(jī)制??
JVM中類的裝載是由ClassLoader和它的子類來實(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)問題的地方,忘記或者錯(cuò)誤的內(nèi)存回收會(huì)導(dǎo)致程序或系統(tǒng)的不穩(wěn)定甚至崩潰,Java提供的GC功能可以自動(dòng)監(jiān)測(cè)對(duì)象是否超過作用域從而達(dá)到自動(dòng)回收內(nèi)存的目的,Java語言沒有提供釋放已分配內(nèi)存的顯示操作方法。
?
69、垃圾回收的優(yōu)點(diǎn)和原理。并考慮2種回收機(jī)制。?
Java語言中一個(gè)顯著的特點(diǎn)就是引入了垃圾回收機(jī)制,使c++程序員最頭疼的內(nèi)存管理的問題迎刃而解,它使得Java程序員在編寫程序的時(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í)間沒有使用的對(duì)象進(jìn)行清楚和回收,程序員不能實(shí)時(shí)的調(diào)用垃圾回收器對(duì)某個(gè)對(duì)象或所有對(duì)象進(jìn)行垃圾回收。回收機(jī)制有分代復(fù)制垃圾回收和標(biāo)記垃圾回收,增量垃圾回收。
?
70、垃圾回收器的基本原理是什么?垃圾回收器可以馬上回收內(nèi)存嗎?有什么辦法主動(dòng)通知虛擬機(jī)進(jìn)行垃圾回收??
對(duì)于GC來說,當(dāng)程序員創(chuàng)建對(duì)象時(shí),GC就開始監(jiān)控這個(gè)對(duì)象的地址、大小以及使用情況。通常,GC采用有向圖的方式記錄和管理堆(heap)中的所有對(duì)象。通過這種方式確定哪些對(duì)象是"可達(dá)的",哪些對(duì)象是"不可達(dá)的"。當(dāng)GC確定一些對(duì)象為"不可達(dá)"時(shí),GC就有責(zé)任回收這些內(nèi)存空間。可以。程序員可以手動(dòng)執(zhí)行System.gc(),通知GC運(yùn)行,但是Java語言規(guī)范并不保證GC一定會(huì)執(zhí)行。?
?
?
71、什么時(shí)候用assert。?
assertion(斷言)在軟件開發(fā)中是一種常用的調(diào)試方式,很多開發(fā)語言中都支持這種機(jī)制。在實(shí)現(xiàn)中,assertion就是在程序中的一條語句,它對(duì)一個(gè)boolean表達(dá)式進(jìn)行檢查,一個(gè)正確程序必須保證這個(gè)boolean表達(dá)式的值為true;如果該值為false,說明程序已經(jīng)處于不正確的狀態(tài)下,assert將給出警告或退出。一般來說,assertion用于保證程序最基本、關(guān)鍵的正確性。assertion檢查通常在開發(fā)和測(cè)試時(shí)開啟。為了提高性能,在軟件發(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)的問題,例如有兩個(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)景,通俗地說,就是程序員可能創(chuàng)建了一個(gè)對(duì)象,以后一直不再使用這個(gè)對(duì)象,這個(gè)對(duì)象卻一直被引用,即這個(gè)對(duì)象無用但是卻無法被垃圾回收器回收的,這就是java中可能出現(xiàn)內(nèi)存泄露的情況,例如,緩存系統(tǒng),我們加載了一個(gè)對(duì)象放在緩存中(例如放在一個(gè)全局map對(duì)象中),然后一直不再使用它,這個(gè)對(duì)象一直被緩存引用,但卻不再被使用。
檢查java中的內(nèi)存泄露,一定要讓程序?qū)⒏鞣N分支情況都完整執(zhí)行到程序結(jié)束,然后看某個(gè)對(duì)象是否被使用過,如果沒有,則才能判定這個(gè)對(duì)象屬于內(nèi)存泄露。
?
下面內(nèi)容來自于網(wǎng)上(主要特點(diǎn)就是清空堆棧中的某個(gè)元素,并不是徹底把它從數(shù)組中拿掉,而是把存儲(chǔ)的總數(shù)減少,本人寫得可以比這個(gè)好,在拿掉某個(gè)元素時(shí),順便也讓它從數(shù)組中消失,將那個(gè)元素所在的位置的值設(shè)置為null即可):
我實(shí)在想不到比那個(gè)堆棧更經(jīng)典的例子了,以致于我還要引用別人的例子,下面的例子不是我想到的,是書上看到的,當(dāng)然如果沒有在書上看到,可能過一段時(shí)間我自己也想的到,可是那時(shí)我說是我自己想到的也沒有人相信的。
????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è)元素,然后全部彈出來,雖然堆棧是空的,沒有我們要的東西,但是這是個(gè)對(duì)象是無法回收的,這個(gè)才符合了內(nèi)存泄露的兩個(gè)條件:無用,無法回收。
????但是就是存在這樣的東西也不一定會(huì)導(dǎo)致什么樣的后果,如果這個(gè)堆棧用的比較少,也就浪費(fèi)了幾個(gè)K內(nèi)存而已,反正我們的內(nèi)存都上G了,哪里會(huì)有什么影響,再說這個(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,就一直存在到程序退出,但是我們也可以看到它有自愈功能,就是說如果你的Stack最多有100個(gè)對(duì)象,那么最多也就只有100個(gè)對(duì)象無法被回收其實(shí)這個(gè)應(yīng)該很容易理解,Stack內(nèi)部持有100個(gè)引用,最壞的情況就是他們都是無用的,因?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)友正好問過這個(gè)問題,我覺得挺有趣,就研究了一下,沒想到今天還被你面到了,哈哈。
在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、說出一些常用的類,包,接口,請(qǐng)各舉5個(gè)?
要讓人家感覺你對(duì)java?ee開發(fā)很熟,所以,不能僅僅只列core?java中的那些東西,要多列你在做ssh項(xiàng)目中涉及的那些東西。就寫你最近寫的那些程序中涉及的那些類。
?
常用的類: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問題
75、能不能自己寫個(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)用程序中寫一個(gè)java.lang.String,這時(shí)候Servlet程序加載的就是我們自己寫的java.lang.String,但是這么干就會(huì)出很多潛在的問題,原來所有用了java.lang.String類的都將出現(xià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,而該類中沒有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ò)。局部變量前不能放置任何訪問修飾符?(private,public,和protected)。final可以用來修飾局部變量
(final如同abstract和strictfp,都是非訪問修飾符,strictfp只能修飾class和method而非variable)。
3.
abstract?class?Something?{
???private?abstract?String?doSomething?();
}
這好像沒什么錯(cuò)吧?
答案:?錯(cuò)。abstract的methods不能以private修飾。abstract的methods就是讓子類implement(實(shí)現(xiàn))具體細(xì)節(jié)的,怎么可以用private把a(bǔ)bstract
method封鎖起來呢??(同理,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的問題,這有錯(cuò)嗎?
答案:?正確。在addOne?method中,參數(shù)o被修飾成final。如果在addOne?method里我們修改了o的reference
(比如:?o?=?new?Other();),那么如同上例這題也是錯(cuò)的。但這里修改的是o的member?vairable
(成員變量),而o的reference并沒有改變。
6.
class?Something?{
????int?i;
????public?void?doSomething()?{
????????System.out.println("i?=?"?+?i);
????}
}?
有什么錯(cuò)呢??看不出來啊。
答案:?正確。輸出的是"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沒有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ò)。看上去在main里call?doSomething沒有什么問題,畢竟兩個(gè)methods都在同一個(gè)class里。但仔細(xì)看,main是static的。static?method不能直接call?non-static?methods。可改成"System.out.println("s.doSomething()?returns?"?+?s.doSomething());"。同理,static?method不能訪問non-static?instant?variable。
9.
此處,Something類的文件名叫OtherThing.java
class?Something?{
????private?static?void?main(String[]?something_to_do)?{????????
????????System.out.println("Do?something?...");
????}
}
?這個(gè)好像很明顯。
答案:?正確。從來沒有人說過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來明確,而接口的屬性默認(rèn)隱含為?public?static?final.所以可以通過A.x來明確。
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"沒有問題。interface可繼承多個(gè)interfaces,所以這里沒錯(cuò)。問題出在interface?Rollable里的"Ball?ball?=?new?Ball("PingPang");"。任何在interface里聲明的interface?variable?(接口變量,也可稱成員變量),默認(rèn)為public?static?final。也就是說"Ball?ball?=?new?Ball("PingPang");"實(shí)際上是"public?static?final?Ball?ball?=?new?Ball("PingPang");"。在Ball類的Play()方法中,"ball?=?new?Ball("Football");"改變了ball的reference,而這里的ball來自Rollable?interface,Rollable?interface里的ball是public?static?final的,final的object是不能被改變r(jià)eference的。因此編譯器將在"ball?=?new?Ball("Football");"這里顯示有錯(cuò)。
2.?算法與編程
77、說明生活中遇到的二叉樹,用java實(shí)現(xiàn)二叉樹
我有很多個(gè)(假設(shè)10萬個(gè))數(shù)據(jù)要保存起來,以后還需要從保存的這些數(shù)據(jù)中檢索是否存在某個(gè)數(shù)據(jù),(我想說出二叉樹的好處,該怎么說呢?那就是說別人的缺點(diǎn)),假如存在數(shù)組中,那么,碰巧要找的數(shù)字位于99999那個(gè)地方,那查找的速度將很慢,因?yàn)橐獜牡?個(gè)依次往后取,取出來后進(jìn)行比較。平衡二叉樹(構(gòu)建平衡二叉樹需要先排序,我們這里就不作考慮了)可以很好地解決這個(gè)問題,但二叉樹的遍歷(前序,中序,后序)效率要比數(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)問也是可以的。還要加上實(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
?
//下面的代碼沒有執(zhí)行,說明往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ù)相同的其他姓名就打印不出來。
?*?*/
?
//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、寫一個(gè)Singleton出來。
Singleton模式主要作用是保證在Java應(yīng)用程序中,一個(gè)類Class只有一個(gè)實(shí)例存在。?
一般Singleton模式通常有幾種種形式:?
第一種形式:?定義一個(gè)類,它的構(gòu)造函數(shù)為private的,它有一個(gè)static的private的該類變量,在類初始化時(shí)實(shí)例話,通過一個(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è)供外部訪問本class的靜態(tài)方法,可以直接訪問 ?
????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í),把值按照指定順序輸出來。
例: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è)快速排序。?
?本人只研究過冒泡排序、選擇排序和快速排序,下面是快速排序的代碼:
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)換成中國傳統(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[]{
'元','拾','佰','仟','萬','拾','佰','仟','億'
};
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í)間,比如說月份不大于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)寫出用于校驗(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、說一說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í)例銷毀的時(shí)候調(diào)用其destroy方法。
web容器加載servlet,生命周期開始。通過調(diào)用servlet的init()方法進(jìn)行servlet的初始化。通過調(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頁面中的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ù)器直接訪問目標(biāo)地址的URL,把那個(gè)URL的響應(yīng)內(nèi)容讀取過來,然后把這些內(nèi)容再發(fā)給瀏覽器,瀏覽器根本不知道服務(wù)器發(fā)送的內(nèi)容是從哪兒來的,所以它的地址欄中還是原來的地址。?
???redirect就是服務(wù)端根據(jù)邏輯,發(fā)送一個(gè)狀態(tài)碼,告訴瀏覽器重新去請(qǐng)求那個(gè)地址,一般來說瀏覽器會(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ì)包含來自GET/POST請(qǐng)求的參數(shù)?
response?網(wǎng)頁傳回用戶端的回應(yīng)?
pageContext?網(wǎng)頁的屬性是在這里管理?
session?與請(qǐng)求有關(guān)的會(huì)話期?
application?servlet?正在執(zhí)行的內(nèi)容?
out?用來傳送回應(yīng)的輸出?
config?servlet的構(gòu)架部件?
page?JSP網(wǎng)頁本身?
exception?針對(duì)錯(cuò)誤網(wǎng)頁,未捕捉的例外?
?
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表示從該頁面產(chǎn)生的一個(gè)servlet實(shí)例?
?
99.?jsp有哪些動(dòng)作?作用分別是什么??
(這個(gè)問題似乎不重要,不明白為何有此題)
答:JSP共有以下6種基本動(dòng)作?
jsp:include:在頁面被請(qǐng)求的時(shí)候引入一個(gè)文件。?
jsp:useBean:尋找或者實(shí)例化一個(gè)JavaBean。?
jsp:setProperty:設(shè)置JavaBean的屬性。?
jsp:getProperty:輸出某個(gè)JavaBean的屬性。?
jsp:forward:把請(qǐng)求轉(zhuǎn)到一個(gè)新的頁面。?
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)頁面,并且可以帶參數(shù)?靜態(tài)INCLUDE用include偽碼實(shí)現(xiàn),定不會(huì)檢查所含文件的變化,適用于包含靜態(tài)頁面?<%@?include?file=included.htm?%>?
?
102、兩種跳轉(zhuǎn)方式分別是什么?有什么區(qū)別??
(下面的回答嚴(yán)重錯(cuò)誤,應(yīng)該是想問forward和sendRedirect?的區(qū)別,畢竟出題的人不是專業(yè)搞文字藝術(shù)的人,可能表達(dá)能力并不見得很強(qiáng),用詞不一定精準(zhǔn),加之其自身的技術(shù)面也可能存在一些問題,不一定真正將他的意思表達(dá)清楚了,嚴(yán)格意思上來講,一些題目可能根本就無人能答,所以,答題時(shí)要掌握主動(dòng),只要把自己知道的表達(dá)清楚就夠了,而不要去推敲原始題目的具體含義是什么,不要一味想著是在答題)
答:有兩種,分別為:?
<jsp:include?page=included.jsp?flush=true>?
<jsp:forward?page=?nextpage.jsp/>?
前者頁面不會(huì)轉(zhuǎn)向include所指的頁面,只是顯示該頁的結(jié)果,主頁面還是原來的頁面。執(zhí)行完后還會(huì)回來,相當(dāng)于函數(shù)調(diào)用。并且可以帶參數(shù).后者完全轉(zhuǎn)向新頁面,不會(huì)再回來。相當(dāng)于go?to?語句。
?
103、頁面間對(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里分離開來。而JSP的情況是Java和HTML可以組合成一個(gè)擴(kuò)展名為.jsp的文件。JSP側(cè)重于視圖,Servlet主要用于控制邏輯。?
?
105、MVC的各個(gè)部分都有那些技術(shù)來實(shí)現(xiàn)?如何實(shí)現(xiàn)??
答:MVC是Model-View-Controller的簡(jiǎn)寫。Model?代表的是應(yīng)用的業(yè)務(wù)邏輯(通過JavaBean,EJB組件實(shí)現(xiàn)),?View?是應(yīng)用的表示面(由JSP頁面產(chǎn)生),Controller?是提供應(yīng)用的處理過程控制(一般是一個(gè)Servlet),通過這種設(shè)計(jì)模型把應(yīng)用邏輯,處理過程和顯示邏輯分成不同的組件實(shí)現(xiàn)。這些組件可以進(jìn)行交互和重用。?
?
106、我們?cè)趙eb應(yīng)用開發(fā)過程中經(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),分開;然后可選擇升或者降序排序;按提交鍵就在另一頁面顯示按什么排序,結(jié)果為,提供reset
108.?數(shù)據(jù)庫部分
109、數(shù)據(jù)庫三范式是什么?
第一范式:1NF是對(duì)屬性的原子性約束,要求屬性具有原子性,不可再分解
第二范式:2NF是對(duì)記錄的唯一約束,要求記錄有唯一標(biāo)識(shí),即實(shí)體的唯一性
第三范式:3NF是對(duì)字段行的約束,即任何字段不能由其他字段派生出來,要求字段沒有余,,(是直接相關(guān)而不是間接相關(guān))
110、說出一些數(shù)據(jù)庫優(yōu)化方面的經(jīng)驗(yàn)?
111、union和union?all有什么不同?
Union會(huì)自動(dòng)壓縮多個(gè)結(jié)果集合中的重復(fù)結(jié)果,而union?all則將所有的結(jié)果全部顯示出來,不管是不是重復(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ù)庫中有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語句是對(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í),也要寫出每個(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)就引出迪卡爾既的問題。假設(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)行改寫,改寫成顯示老師的名字
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;
?
第二種寫法:
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àn)閙ax只有一列,不能與其他列混淆。
?
select?authorid,count(*)?total?from?articles?
group?by?authorid?having?total=max(total)也不行。
114、什么是存儲(chǔ)過程和如何編寫
存儲(chǔ)過程是一組為了完成特定功能的sql語句集,
create?or?replace
procedure?test
as
begin
??過程
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ǔ)過程
{call過程名[(?,?,,,,)]}返回結(jié)果參數(shù)的過程的語法為
{?=call過程名[(?,?,,,,)]}
不帶參的:{call過程名}
117、JDBC中的PreparedStatement相比Statement的好處
1,相對(duì)比較安全,可以防止sql注入
2,有裕編譯功能,相同的操作批量數(shù)據(jù)效率較高
118.?寫一個(gè)用jdbc連接并訪問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不一樣,)
用:比如說給你以個(gè)字符串(代表以類的包名和類名),要你把他的類加載到虛擬機(jī)上的時(shí)候就要用到了,
答:調(diào)用該訪問返回一個(gè)以字符串指定類名的類的對(duì)象。
120、大數(shù)據(jù)量下的分頁解決方法。
121、用?JDBC?查詢學(xué)生成績(jī)單,?把主要代碼寫出來.?
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、說出數(shù)據(jù)連接池的工作機(jī)制是什么??
J2EE服務(wù)器啟動(dòng)時(shí)會(huì)建立一定數(shù)量的池連接,并一直維持不少于此數(shù)目的池連接。客戶端程序需要連接時(shí),池驅(qū)動(dòng)程序會(huì)返回一個(gè)未使用的池連接并將其表記為忙。如果當(dāng)前沒有空閑連接,池驅(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ù)庫對(duì)象之間的映射關(guān)系,程序員不需要編寫復(fù)雜的sql語句,直接操作java對(duì)象即可,從而大大降低了代碼量,也是程序員更加專注于業(yè)務(wù)邏輯的實(shí)現(xiàn),
1.?代碼繁瑣問題,用jdbc訪問數(shù)據(jù)庫代碼量大繁瑣,容易出錯(cuò),
2.?數(shù)據(jù)庫連接問題,,關(guān)系數(shù)據(jù)對(duì)象之間,存在各種關(guān)系,,如果程序員用jdbc編程的話,就必須十分小心的處理這些關(guān)系,而這個(gè)過程是個(gè)很痛苦的過程,
3.?Orm建立java對(duì)象與數(shù)據(jù)庫對(duì)象關(guān)系映射,也自動(dòng)根據(jù)數(shù)據(jù)庫對(duì)象之間的關(guān)系創(chuàng)建java對(duì)象的關(guān)系,并且提供了維持這些關(guān)系的完整有效機(jī)制
4.?系統(tǒng)架構(gòu)問題,現(xiàn)在的應(yīng)用系統(tǒng)一般由展示層,業(yè)務(wù)層,數(shù)據(jù)訪問層,數(shù)據(jù)層,各層次功能劃分非常清楚,jdbc屬于數(shù)據(jù)訪問層,使用jdbc編程時(shí)就必須知道后臺(tái)使用的是什么數(shù)據(jù)庫,有哪些表,哪些字段,表與表之間有什么關(guān)系,索引,等等,,使用orm可以完全的屏蔽數(shù)據(jù)庫,給程序員的只有java對(duì)象,程序員只需要根據(jù)業(yè)務(wù)邏輯的需要調(diào)用java對(duì)象,就可以實(shí)現(xiàn)對(duì)后臺(tái)的數(shù)據(jù)庫操作
5.?性能問題,jdbc很多時(shí)候存在效率地下的問題,orm框架講根據(jù)具體數(shù)據(jù)庫操作需要,會(huì)自動(dòng)的延遲向后臺(tái)數(shù)據(jù)庫發(fā)送sql請(qǐng)求,盡量減少不必要的數(shù)據(jù)操作請(qǐng)求操作,
?
5.?XML部分
125、xml有哪些解析技術(shù)?區(qū)別是什么??
答:有DOM,SAX,STAX等?
DOM:處理大型文件時(shí)其性能下降的非常厲害。這個(gè)問題是由DOM的樹結(jié)構(gòu)所造成的,這種結(jié)構(gòu)占用的內(nèi)存較多,而且DOM必須在解析文件之前把整個(gè)文檔裝入內(nèi)存,適合對(duì)XML的隨機(jī)訪問SAX:不現(xiàn)于DOM,SAX是事件驅(qū)動(dòng)型的XML解析方式。它順序讀取XML文件,不需要一次全部裝載整個(gè)文件。當(dāng)遇到像文件開頭,文檔結(jié)束,或者標(biāo)簽開頭與標(biāo)簽結(jié)束時(shí),它會(huì)觸發(fā)一個(gè)事件,用戶通過在其回調(diào)事件中寫入處理代碼來處理XML文件,適合對(duì)XML的順序訪問?
STAX:Streaming?API?for?XML?(StAX)?
講解這些區(qū)別是不需要特別去比較,就像說傳智播客與其他培訓(xùn)機(jī)構(gòu)的區(qū)別時(shí),我們只需說清楚傳智播客有什么特點(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文件壓縮打包加密后通過網(wǎng)絡(luò)傳送給接收者,接收解密與解壓縮后再同XML文件中還原相關(guān)信息進(jìn)行處理。在做軟件配置時(shí),利用XML可以很方便的進(jìn)行,軟件的各種配置參數(shù)都存貯在XML文件中。?
127、用jdom解析xml文件時(shí)如何解決中文問題?如何解析??
答:看如下代碼,用編碼方式加以解決?
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è)問題是由DOM的樹結(jié)構(gòu)所造成的,這種結(jié)構(gòu)占用的內(nèi)存較多,而且DOM必須在解析文件之前把整個(gè)文檔裝入內(nèi)存,適合對(duì)XML的隨機(jī)訪問?
SAX:不現(xiàn)于DOM,SAX是事件驅(qū)動(dòng)型的XML解析方式。它順序讀取XML文件,不需要一次全部裝載整個(gè)文件。當(dāng)遇到像文件開頭,文檔結(jié)束,或者標(biāo)簽開頭與標(biāo)簽結(jié)束時(shí),它會(huì)觸發(fā)一個(gè)事件,用戶通過在其回調(diào)事件中寫入處理代碼來處理XML文件,適合對(duì)XML的順序訪問?
???STAX:Streaming?API?for?XML?(StAX)?
?
6.?j2ee部分
130、BS與CS的聯(lián)系與區(qū)別。?
C/S是Client/Server的縮寫。服務(wù)器通常采用高性能的PC、工作站或小型機(jī),并采用大型數(shù)據(jù)庫系統(tǒng),如Oracle、Sybase、InFORMix或?SQL?Server。客戶端需要安裝專用的客戶端軟件。?
B/S是Brower/Server的縮寫,客戶機(jī)上只要安裝一個(gè)瀏覽器(Browser),如Netscape?Navigator或Internet?Explorer,服務(wù)器安裝Oracle、Sybase、InFORMix或?SQL?Server等數(shù)據(jù)庫。在這種結(jié)構(gòu)下,用戶界面完全通過WWW瀏覽器實(shí)現(xiàn),一部分事務(wù)邏輯在前端實(shí)現(xiàn),但是主要事務(wù)邏輯在服務(wù)器端實(shí)現(xiàn)。瀏覽器通過Web?Server?同數(shù)據(jù)庫進(jìn)行數(shù)據(jù)交互。?
C/S?與?B/S?區(qū)別:?
1.硬件環(huán)境不同:?
C/S?一般建立在專用的網(wǎng)絡(luò)上,?小范圍里的網(wǎng)絡(luò)環(huán)境,?局域網(wǎng)之間再通過專門服務(wù)器提供連接和數(shù)據(jù)交換服務(wù).?
B/S?建立在廣域網(wǎng)之上的,?不必是專門的網(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)適宜.?可以通過B/S發(fā)布部分可公開信息.?
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ì)安全以及訪問速度的多重的考慮,?建立在需要更加優(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ì)較好的重用.就入買來的餐桌可以再利用,而不是做在墻上的石頭桌子?
5.系統(tǒng)維護(hù)不同???
C/S?程序由于整體性,?必須整體考察,?處理出現(xiàn)的問題以及系統(tǒng)升級(jí).?升級(jí)難.?可能是再做一個(gè)全新的系統(tǒng)?
B/S?構(gòu)件組成,方面構(gòu)件個(gè)別的更換,實(shí)現(xiàn)系統(tǒng)的無縫升級(jí).?系統(tǒng)維護(hù)開銷減到最小.用戶從網(wǎng)上自己下載安裝就可以實(shí)現(xiàn)升級(jí).?
6.處理問題不同?
C/S?程序可以處理用戶面固定,?并且在相同區(qū)域,?安全要求高需求,?與操作系統(tǒng)相關(guān).?應(yīng)該都是相同的系統(tǒng)?
B/S?建立在廣域網(wǎng)上,?面向不同的用戶群,?分散地域,?這是C/S無法作到的.?與操作系統(tǒng)平臺(tái)關(guān)系最小.?
7.用戶接口不同?
C/S?多是建立的Window平臺(tái)上,表現(xiàn)方法有限,對(duì)程序員普遍要求較高?
B/S?建立在瀏覽器上,?有更加豐富和生動(dòng)的表現(xiàn)方式與用戶交流.?并且大部分難度減低,減低開發(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)用的開發(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)問題。主要有WEB服務(wù)器來實(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)行高效率的管理。并且可以通過現(xiàn)成的接口來獲得系統(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)證框架。提供一些安全控制方面的框架。讓開發(fā)者通過各種部署和自定義實(shí)現(xiàn)自己的個(gè)性安全控制策略。?
RMI/IIOP:(Remote?Method?Invocation?/internet對(duì)象請(qǐng)求中介協(xié)議)他們主要用于通過遠(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ī)范才能在異構(gòu)的系統(tǒng)之間進(jìn)行通信。RMI是JAVA特有的。
136、如何給weblogic指定大小的內(nèi)存??
(這個(gè)問題不作具體回答,列出來只是告訴讀者可能會(huì)遇到什么問題,你不需要面面俱到,什么都精通。)(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)模式(開發(fā)模式)與產(chǎn)品發(fā)布模式??
可以在管理控制臺(tái)中修改對(duì)應(yīng)服務(wù)器的啟動(dòng)模式為開發(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文件中增加加密過的用戶名和密碼.?
139、在weblogic管理制臺(tái)中對(duì)一個(gè)應(yīng)用域(或者說是一個(gè)網(wǎng)站,Domain)進(jìn)行jms及ejb或連接池等相關(guān)信息進(jìn)行配置后,實(shí)際保存在什么文件中??
保存在此Domain的config.xml文件中,它是服務(wù)器的核心配置文件。?
140、說說weblogic中一個(gè)Domain的缺省目錄結(jié)構(gòu)?比如要將一個(gè)簡(jiǎn)單的helloWorld.jsp放入何目錄下,然的在瀏覽器上就可打入http://主機(jī):端口號(hào)//helloword.jsp就可以看到運(yùn)行結(jié)果了??又比如這其中用到了一個(gè)自己寫的javaBean該如何辦??
Domain目錄服務(wù)器目錄applications,將應(yīng)用目錄放在此目錄下將可以作為應(yīng)用訪問,如果是Web應(yīng)用,應(yīng)用目錄需要滿足Web應(yīng)用目錄要求,jsp文件可以直接放在應(yīng)用目錄中,Javabean需要放在應(yīng)用目錄的WEB-INF目錄的classes目錄中,設(shè)置服務(wù)器的缺省應(yīng)用將可以實(shí)現(xiàn)在瀏覽器上無需輸入應(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)證配置或說說j2ee(標(biāo)準(zhǔn))進(jìn)行ssl的配置?
缺省安裝中使用DemoIdentity.jks和DemoTrust.jks??KeyStore實(shí)現(xiàn)SSL,需要配置服務(wù)器使用Enable?SSL,配置其端口,在產(chǎn)品模式下需要從CA獲取私有密鑰和數(shù)字證書,創(chuàng)建identity和trust?keystore,裝載獲得的密鑰和數(shù)字證書。可以配置此SSL連接是單向還是雙向的。?
147、如何查看在weblogic中已經(jīng)發(fā)布的EJB??
可以使用管理控制臺(tái),在它的Deployment中可以查看所有已發(fā)布的EJB?
7.?ejb部分
148、EJB是基于哪些技術(shù)實(shí)現(xiàn)的?并說出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)用程序中被用來完成一些服務(wù)器端的業(yè)務(wù)操作,例如訪問數(shù)據(jù)庫、調(diào)用其他EJB組件。EntityBean被用來代表應(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),因此通常來說,一個(gè)使用者會(huì)有一個(gè)相對(duì)應(yīng)的?Stateful?Session?Bean?的實(shí)體。Stateless?Session?Bean?雖然也是邏輯組件,但是他卻不負(fù)責(zé)記錄使用者狀態(tài),也就是說當(dāng)使用者呼叫?Stateless?Session?Bean?的時(shí)候,EJB?Container?并不會(huì)找尋特定的?Stateless?Session?Bean?的實(shí)體來執(zhí)行這個(gè)?method。換言之,很可能數(shù)個(gè)使用者在執(zhí)行某個(gè)?Stateless?Session?Bean?的?methods?時(shí),會(huì)是同一個(gè)?Bean?的?Instance?在執(zhí)行。從內(nè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并沒有嚴(yán)格的規(guī)范,理論上講,任何一個(gè)Java類都可以是一個(gè)Bean。但通常情況下,由于Java?Bean是被容器所創(chuàng)建(如Tomcat)的,所以Java?Bean應(yīng)具有一個(gè)無參的構(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)程訪問的。Enterprise?Java?Bean?相當(dāng)于DCOM,即分布式組件。它是基于Java的遠(yuǎn)程方法調(diào)用(RMI)技術(shù)的,所以EJB可以被遠(yuǎn)程訪問(跨進(jìn)程、跨計(jì)算機(jī))。但EJB必須被布署在諸如Webspere、WebLogic這樣的容器中,EJB客戶從不直接訪問真正的EJB組件,而是通過其容器訪問。EJB容器是EJB組件的代理,EJB組件由容器所創(chuàng)建和管理。客戶通過容器來訪問真正的EJB組件。?
151、EJB包括(SessionBean,EntityBean)說出他們的生命周期,及如何管理事務(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ù)庫中的數(shù)據(jù)存在,Entity?beans就一直存活。而不是按照應(yīng)用程序或者服務(wù)進(jìn)程來說的。即使EJB容器崩潰了,Entity?beans也是存活的。Entity?Beans生命周期能夠被容器或者?Beans自己管理。?
EJB通過以下技術(shù)管理實(shí)務(wù):對(duì)象管理組織(OMG)的對(duì)象實(shí)務(wù)服務(wù)(OTS),Sun?Microsystems的Transaction?Service(JTS)、Java?Transaction?API(JTA),開發(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)自己沒有綁定對(duì)應(yīng)的Bean實(shí)例則從其去激活Bean存儲(chǔ)中(通過序列化機(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)和無狀態(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接口,通過Remote接口調(diào)用其業(yè)務(wù)方法。
156.?webservice部分
157、WEB?SERVICE名詞解釋。JSWDL開發(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通信提供訪問方法和傳輸機(jī)制的API。?
WSDL是一種?XML?格式,用于將網(wǎng)絡(luò)服務(wù)描述為一組端點(diǎn),這些端點(diǎn)對(duì)包含面向文檔信息或面向過程信息的消息進(jìn)行操作。這種格式首先對(duì)操作和消息進(jìn)行抽象描述,然后將其綁定到具體的網(wǎng)絡(luò)協(xié)議和消息格式上以定義端點(diǎn)。相關(guān)的具體端點(diǎn)即組合成為抽象端點(diǎn)(服務(wù))。?
SOAP即簡(jiǎn)單對(duì)象訪問協(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)的訪問協(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,縮寫為?OMG)標(biāo)準(zhǔn)化。它的組成是接口定義語言(IDL),?語言綁定(binding:也譯為聯(lián)編)和允許應(yīng)用程序間互操作的協(xié)議。?其目的為:用不同的程序設(shè)計(jì)語言書寫在不同的進(jìn)程中運(yùn)行,為不同的操作系統(tǒng)開發(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)清晰,使開發(fā)者只關(guān)注業(yè)務(wù)邏輯的實(shí)現(xiàn).
2.有豐富的tag可以用?,Struts的標(biāo)記庫(Taglib),如能靈活動(dòng)用,則能大大提高開發(fā)效率
3.?頁面導(dǎo)航
使系統(tǒng)的脈絡(luò)更加清晰。通過一個(gè)配置文件,即可把握整個(gè)系統(tǒng)各部分之間的聯(lián)系,這對(duì)于后期的維護(hù)有著莫大的好處。尤其是當(dāng)另一批開發(fā)者接手這個(gè)項(xiàng)目時(shí),這種優(yōu)勢(shì)體現(xiàn)得更加明顯。
4.?提供Exception處理機(jī)制?.?
5.?數(shù)據(jù)庫鏈接池管理?
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è)就引起了線程安全的問題。
三、??測(cè)試不方便.?Struts的每個(gè)Action都同Web層耦合在一起,這樣它的測(cè)試依賴于Web容器,單元測(cè)試也很難實(shí)現(xiàn)。不過有一個(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的依賴性過強(qiáng).?Struts處理Action時(shí)必需要依賴ServletRequest?和ServletResponse,所有它擺脫不了Servlet容器。?
六、??前端表達(dá)式語言方面.Struts集成了JSTL,所以它主要使用JSTL的表達(dá)式語言來獲取數(shù)據(jù)。可是JSTL的表達(dá)式語言在Collection和索引屬性方面處理顯得很弱。?
七、??對(duì)Action執(zhí)行的控制困難.?Struts創(chuàng)建一個(gè)Action,如果想控制它的執(zhí)行順序?qū)?huì)非常困難。甚至你要重新去寫Servlet來實(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),換一句話說:在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ù),開發(fā)Web應(yīng)用程序的開放源碼的framework。?采用Struts能開發(fā)出基于MVC(Model-View-Controller)設(shè)計(jì)模式的應(yīng)用構(gòu)架。?Struts有如下的主要功能:?一.包含一個(gè)controller?servlet,能將用戶的請(qǐng)求發(fā)送到相應(yīng)的Action對(duì)象。?二.JSP自由tag庫,并且在controller?servlet中提供關(guān)聯(lián)支持,幫助開發(fā)員創(chuàng)建交互式表單應(yīng)用。?三.提供了一系列實(shí)用對(duì)象:XML處理、通過Java?reflection?APIs自動(dòng)處理JavaBeans屬性、國際化的提示和消息。
?
162、hibernate中的update()和saveOrUpdate()的區(qū)別,session的load()和get()的區(qū)別。
?
163、簡(jiǎn)述?Hibernate?和?JDBC?的優(yōu)缺點(diǎn)??如何書寫一個(gè)?one?to?many?配置文件.
164、iBatis與Hibernate有什么不同?
相同點(diǎn):屏蔽jdbc?api的底層訪問細(xì)節(jié),使用我們不用與jdbc?api?打交道,就可以訪問數(shù)據(jù),jdbc?api編程流程固定,
165.?hibernate進(jìn)行多表查詢每個(gè)表中各取幾個(gè)字段,也就是說查詢出來的結(jié)果集沒有一個(gè)實(shí)體類與之對(duì)應(yīng)如何解決;?
?
解決方案一,按照Object[]數(shù)據(jù)取出數(shù)據(jù),然后自己組bean
解決方案二,對(duì)每個(gè)表的bean寫構(gòu)造函數(shù),比如表一要查出field1,field2兩個(gè)字段,那么有一個(gè)構(gòu)造函數(shù)就是Bean(type1?filed1,type2?
field2)?,然后在hql里面就可以直接生成這個(gè)bean了。
166.介紹一下Hibernate的二級(jí)緩存
按照以下思路來回答:(1)首先說清楚什么是緩存,(2)再說有了hibernate的Session就是一級(jí)緩存,即有了一級(jí)緩存,為什么還要有二級(jí)緩存,(3)最后再說如何配置Hibernate的二級(jí)緩存。
(1)緩存就是把以前從數(shù)據(jù)庫中查詢出來和使用過的對(duì)象保存在內(nèi)存中(一個(gè)數(shù)據(jù)結(jié)構(gòu)中),這個(gè)數(shù)據(jù)結(jié)構(gòu)通常是或類似Hashmap,當(dāng)以后要使用某個(gè)對(duì)象時(shí),先查詢緩存中是否有這個(gè)對(duì)象,如果有則使用緩存中的對(duì)象,如果沒有則去查詢數(shù)據(jù)庫,并將查詢出來的對(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ù)庫中查詢出一個(gè)對(duì)象時(shí),Session也是先從自己內(nèi)部查看是否存在這個(gè)對(duì)象,存在則直接返回,不存在才去訪問數(shù)據(jù)庫,并將查詢的結(jié)果保存在自己內(nèi)部。由于Session代表一次會(huì)話過程,一個(gè)Session與一個(gè)數(shù)據(jù)庫連接相關(guān)連,所以Session最好不要長(zhǎng)時(shí)間保持打開,通常僅用于一個(gè)事務(wù)當(dāng)中,在事務(wù)結(jié)束時(shí)就應(yīng)關(guān)閉。并且Session是線程不安全的,被多個(gè)線程共享時(shí)容易出現(xiàn)問題。通常只有那種全局意義上的緩存才是真正的緩存應(yīng)用,才有較大的緩存價(jià)值,因此,Hibernate的Session這一級(jí)緩存的緩存作用并不明顯,應(yīng)用價(jià)值不大。Hibernate的二級(jí)緩存就是要為Hibernate配置一種全局緩存,讓多個(gè)線程和多個(gè)事務(wù)都可以共享這個(gè)緩存。我們希望的是一個(gè)人使用過,其他人也可以使用,session沒有這種效果。
(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ù)庫中的數(shù)據(jù),當(dāng)使用Hibernate?的二級(jí)緩存后,注意不要有其他的應(yīng)用或SessionFactory來更改當(dāng)前數(shù)據(jù)庫中的數(shù)據(jù),這樣緩存的數(shù)據(jù)就會(huì)與數(shù)據(jù)庫中的實(shí)際數(shù)據(jù)不一致。?
?
167、Spring?的依賴注入是什么意思??給一個(gè)?Bean?的?message?屬性,?字符串類型,?注入值為?"Hello"?的?XML?配置文件該怎么寫?
?
168、Jdo是什么??
JDO是Java對(duì)象持久化的新的規(guī)范,為java?data?object的簡(jiǎn)稱,也是一個(gè)用于存取某種數(shù)據(jù)倉庫中的對(duì)象的標(biāo)準(zhǔn)化API。JDO提供了透明的對(duì)象存儲(chǔ),因此對(duì)開發(fā)人員來說,存儲(chǔ)數(shù)據(jù)對(duì)象完全不需要額外的代碼(如JDBC?API的使用)。這些繁瑣的例行工作已經(jīng)轉(zhuǎn)移到JDO產(chǎn)品提供商身上,使開發(fā)人員解脫出來,從而集中時(shí)間和精力在業(yè)務(wù)邏輯上。另外,JDO很靈活,因?yàn)樗梢栽谌魏螖?shù)據(jù)底層上運(yùn)行。JDBC只是面向關(guān)系數(shù)據(jù)庫(RDBMS)JDO更通用,提供到任何數(shù)據(jù)底層的存儲(chǔ)功能,比如關(guān)系數(shù)據(jù)庫、文件、XML以及對(duì)象數(shù)據(jù)庫(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)建模語言UML。用例圖,靜態(tài)圖(包括類圖、對(duì)象圖和包圖),行為圖,交互圖(順序圖,合作圖),實(shí)現(xiàn)圖。?
173.?軟件開發(fā)的
174、j2ee常用的設(shè)計(jì)模式?說明工廠模式。?
總共23種,分為三大類:創(chuàng)建型,結(jié)構(gòu)型,行為型
我只記得其中常用的6、7種,分別是:
創(chuàng)建型(工廠、工廠方法、抽象工廠、單例)
結(jié)構(gòu)型(包裝、適配器,組合,代理)
行為(觀察者,模版,策略)
然后再針對(duì)你熟悉的模式談?wù)勀愕睦斫饧纯伞???
?
Java中的23種設(shè)計(jì)模式:?
Factory(工廠模式),??????Builder(建造模式),???????Factory?Method(工廠方法模式),?
Prototype(原始模型模式),Singleton(單例模式),????Facade(門面模式),?
Adapter(適配器模式),????Bridge(橋梁模式),????????Composite(合成模式),?
Decorator(裝飾模式),????Flyweight(享元模式),?????Proxy(代理模式),?
Command(命令模式),??????Interpreter(解釋器模式),?Visitor(訪問者模式),?
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è)基類,該類的子類通過不同的方法實(shí)現(xiàn)了基類中的方法。然后需要定義一個(gè)工廠類,工廠類可以根據(jù)條件生成不同的子類實(shí)例。當(dāng)?shù)玫阶宇惖膶?shí)例后,開發(fā)人員可以調(diào)用基類中的方法而不必考慮到底返回的是哪一個(gè)子類的實(shí)例。?
175、開發(fā)中都用到了那些設(shè)計(jì)模式?用在什么場(chǎng)合??
每個(gè)模式都描述了一個(gè)在我們的環(huán)境中不斷出現(xiàn)的問題,然后描述了該問題的解決方案的核心。通過這種方式,你可以無數(shù)次地使用那些已有的解決方案,無需在重復(fù)相同的工作。主要用到了MVC的設(shè)計(jì)模式。用來開發(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ù)庫中實(shí)現(xiàn)。?
GDI類為圖像設(shè)備編程接口類庫。?
?
10.?問得稀里糊涂的題
177、四種會(huì)話跟蹤技術(shù)?
會(huì)話作用域ServletsJSP?頁面描述?
page否是代表與一個(gè)頁面相關(guān)的對(duì)象和屬性。一個(gè)頁面由一個(gè)編譯好的?Java?servlet?類(可以帶有任何的?include?指令,但是沒有?include?動(dòng)作)表示。這既包括?servlet?又包括被編譯成?servlet?的?JSP?頁面?
request是是代表與?Web?客戶機(jī)發(fā)出的一個(gè)請(qǐng)求相關(guān)的對(duì)象和屬性。一個(gè)請(qǐng)求可能跨越多個(gè)頁面,涉及多個(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è)頁面、請(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開發(fā)包的介紹。JAXP、JAXM的解釋。SOAP、UDDI,WSDL解釋。
180、請(qǐng)把?http://tomcat.apache.org/?首頁的這一段話用中文翻譯一下?
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??
?
?
總結(jié)
- 上一篇: java笔试面试经典问题
- 下一篇: ajax常见错误和使用总结