1. Java基礎(chǔ)部分
基礎(chǔ)部分的順序:基本語法竹海,類相關(guān)的語法慕蔚,內(nèi)部類的語法,繼承相關(guān)的語法斋配,異常的語法孔飒,線程的語法,集合的語法艰争,io的語法坏瞄,虛擬機(jī)方面的語法。
1甩卓、一個".java"源文件中是否可以包括多個類(不是內(nèi)部類)戏锹?有什么限制鸭叙?
可以有多個類,但只能有一個public的類摄狱,并且public的類名必須與文件名相一致。
2、Java有沒有g(shù)oto?
java中的保留字,現(xiàn)在沒有在java中使用。
3父腕、說說&和&&的區(qū)別。
&和&&都可以用作邏輯與的運(yùn)算符青瀑,表示邏輯與(and)璧亮,當(dāng)運(yùn)算符兩邊的表達(dá)式的結(jié)果都為true時,整個運(yùn)算結(jié)果才為true狱窘,否則杜顺,只要有一方為false,則結(jié)果為false蘸炸。
&&還具有短路的功能躬络,即如果第一個表達(dá)式為false,則不再計算第二個表達(dá)式搭儒,例如穷当,對于if(str != null&& !str.equals(“”))表達(dá)式,當(dāng)str為null時淹禾,后面的表達(dá)式不會執(zhí)行馁菜,所以不會出現(xiàn)NullPointerException如果將&&改為&,則會拋出NullPointerException異常铃岔。If(x==33 &++y>0) y會增長汪疮,If(x==33 && ++y>0)不會增長
&還可以用作位運(yùn)算符,當(dāng)&操作符兩邊的表達(dá)式不是boolean類型時毁习,&表示按位與操作智嚷,我們通常使用0x0f來與一個整數(shù)進(jìn)行&運(yùn)算,來獲取該整數(shù)的最低4個bit位纺且,例如盏道,0x31 & 0x0f的結(jié)果為0x01。
備注:這道題先說兩者的共同點载碌,再說出&&和&的特殊之處猜嘱,并列舉一些經(jīng)典的例子來表明自己理解透徹深入、實際經(jīng)驗豐富嫁艇。 f
4朗伶、在JAVA中如何跳出當(dāng)前的多重嵌套循環(huán)?
在Java中步咪,要想跳出多重循環(huán)腕让,可以在外面的循環(huán)語句前定義一個標(biāo)號,然后在里層循環(huán)體的代碼中使用帶有標(biā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;
}
}
另外静袖,我個人通常并不使用標(biāo)號這種方式觉鼻,而是讓外層的循環(huán)條件表達(dá)式的結(jié)果可以受到里層循環(huán)體代碼的控制,例如队橙,要在二維數(shù)組中查找到某個數(shù)字坠陈。
int arr[][] ={{1,2,3},{4,5,6,7},{9}};
boolean found = false;
for(int i=0;i
for(int j=0;j
System.out.println(“i=” + i + “,j=” + j);
if(arr[i][j] ?==5) {
found = true;
break;
}
}
}
5、switch語句能否作用在byte上捐康,能否作用在long上仇矾,能否作用在String上?
在switch(expr1)中,expr1只能是一個整數(shù)表達(dá)式或者枚舉常量(更大字體)解总,整數(shù)表達(dá)式可以是int基本類型或Integer包裝類型贮匕,由于,byte,short,char都可以隱含轉(zhuǎn)換為int花枫,所以,這些類型以及這些類型的包裝類型也是可以的。顯然挨决,long和String類型都不符合switch的語法規(guī)定事甜,并且不能被隱式轉(zhuǎn)換成int類型,所以佳簸,它們不能作用于swtich語句中乙墙。
6、short s1 = 1; s1 = s1 + 1;有什么錯? short s1 = 1; s1 += 1;有什么錯?
對于short s1 = 1; s1 = s1 + 1;由于s1+1運(yùn)算時會自動提升表達(dá)式的類型生均,所以結(jié)果是int型听想,再賦值給short類型s1時,編譯器將報告需要強(qiáng)制轉(zhuǎn)換類型的錯誤疯特。
對于short s1 = 1; s1 += 1;由于 +=是java語言規(guī)定的運(yùn)算符哗魂,java編譯器會對它進(jìn)行特殊處理,因此可以正確編譯漓雅。
7录别、char型變量中能不能存貯一個中文漢字?為什么?
char型變量是用來存儲Unicode編碼的字符的,unicode編碼字符集中包含了漢字邻吞,所以组题,char型變量中當(dāng)然可以存儲漢字啦。不過抱冷,如果某個特殊的漢字沒有被包含在unicode編碼字符集中崔列,那么,這個char型變量中就不能存儲這個特殊漢字。補(bǔ)充說明:unicode編碼占用兩個字節(jié)赵讯,所以盈咳,char類型的變量也是占用兩個字節(jié)。
備注:后面一部分回答雖然不是在正面回答題目边翼,但是鱼响,為了展現(xiàn)自己的學(xué)識和表現(xiàn)自己對問題理解的透徹深入,可以回答一些相關(guān)的知識组底,做到知無不言丈积,言無不盡。
8债鸡、用最有效率的方法算出2乘以8等於幾?
2 << 3江滨,
因為將一個數(shù)左移n位,就相當(dāng)于乘以了2的n次方厌均,那么块蚌,一個數(shù)乘以8只要將其左移3位即可沐序,而位運(yùn)算cpu直接支持的汗侵,效率最高催什,所以,2乘以8等於幾的最效率的方法是2 << 3镊屎。
9惹挟、請設(shè)計一個一百億的計算器
首先要明白這道題目的考查點是什么,一是大家首先要對計算機(jī)原理的底層細(xì)節(jié)要清楚缝驳、要知道加減法的位運(yùn)算原理和知道計算機(jī)中的算術(shù)運(yùn)算會發(fā)生越界的情況连锯,二是要具備一定的面向?qū)ο蟮脑O(shè)計思想。
首先用狱,計算機(jī)中用固定數(shù)量的幾個字節(jié)來存儲的數(shù)值运怖,所以計算機(jī)中能夠表示的數(shù)值是有一定的范圍的,為了便于講解和理解夏伊,我們先以byte類型的整數(shù)為例摇展,它用1個字節(jié)進(jìn)行存儲,表示的最大數(shù)值范圍為-128到+127溺忧。-1在內(nèi)存中對應(yīng)的二進(jìn)制數(shù)據(jù)為11111111咏连,如果兩個-1相加,不考慮Java運(yùn)算時的類型提升鲁森,運(yùn)算后會產(chǎn)生進(jìn)位祟滴,二進(jìn)制結(jié)果為1,11111110,由于進(jìn)位后超過了byte類型的存儲空間歌溉,所以進(jìn)位部分被舍棄垄懂,即最終的結(jié)果為11111110,也就是-2,這正好利用溢位的方式實現(xiàn)了負(fù)數(shù)的運(yùn)算草慧。-128在內(nèi)存中對應(yīng)的二進(jìn)制數(shù)據(jù)為10000000桶蛔,如果兩個-128相加,不考慮Java運(yùn)算時的類型提升冠蒋,運(yùn)算后會產(chǎn)生進(jìn)位羽圃,二進(jìn)制結(jié)果為1,00000000,由于進(jìn)位后超過了byte類型的存儲空間抖剿,所以進(jìn)位部分被舍棄,即最終的結(jié)果為00000000识窿,也就是0斩郎,這樣的結(jié)果顯然不是我們期望的弹澎,這說明計算機(jī)中的算術(shù)運(yùn)算是會發(fā)生越界情況的乍恐,兩個數(shù)值的運(yùn)算結(jié)果不能超過計算機(jī)中的該類型的數(shù)值范圍哺呜。由于Java中涉及表達(dá)式運(yùn)算時的類型自動提升诵姜,我們無法用byte類型來做演示這種問題和現(xiàn)象的實驗艺智,大家可以用下面一個使用整數(shù)做實驗的例子程序體驗一下:
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億的大小姻蚓,所以宋梧,要實現(xiàn)一個一百億的計算器,我們得自己設(shè)計一個類可以用于表示很大的整數(shù)狰挡,并且提供了與另外一個整數(shù)進(jìn)行加減乘除的功能捂龄,大概功能如下:
()這個類內(nèi)部有兩個成員變量,一個表示符號加叁,另一個用字節(jié)數(shù)組表示數(shù)值的二進(jìn)制數(shù)
()有一個構(gòu)造方法倦沧,把一個包含有多位數(shù)值的字符串轉(zhuǎn)換到內(nèi)部的符號和字節(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){
}
}
備注:要想寫出這個類的完整代碼,是非常復(fù)雜的它匕,如果有興趣的話展融,可以參看jdk中自帶的java.math.BigInteger類的源碼。面試的人也知道誰都不可能在短時間內(nèi)寫出這個類的完整代碼的豫柬,他要的是你是否有這方面的概念和意識告希,他最重要的還是考查你的能力,所以轮傍,你不要因為自己無法寫出完整的最終結(jié)果就放棄答這道題暂雹,你要做的就是你比別人寫得多,證明你比別人強(qiáng)创夜,你有這方面的思想意識就可以了杭跪,畢竟別人可能連題目的意思都看不懂,什么都沒寫,你要敢于答這道題涧尿,即使只答了一部分系奉,那也與那些什么都不懂的人區(qū)別出來,拉開了距離姑廉,算是矮子中的高個缺亮,機(jī)會當(dāng)然就屬于你了。另外桥言,答案中的框架代碼也很重要萌踱,體現(xiàn)了一些面向?qū)ο笤O(shè)計的功底,特別是其中的方法命名很專業(yè)号阿,用的英文單詞很精準(zhǔn)并鸵,這也是能力、經(jīng)驗扔涧、專業(yè)性园担、英語水平等多個方面的體現(xiàn),會給人留下很好的印象枯夜,在編程能力和其他方面條件差不多的情況下弯汰,英語好除了可以使你獲得更多機(jī)會外,薪水可以高出一千元湖雹。
10咏闪、使用final關(guān)鍵字修飾一個變量時,是引用不能變,還是引用的對象不能變?
使用final關(guān)鍵字修飾一個變量時谚赎,是指引用變量不能變,引用變量所指向的對象中的內(nèi)容還是可以改變的溪胶。例如,對于如下語句:
final StringBuffer a=new StringBuffer("immutable");
執(zhí)行如下語句將報告編譯期錯誤:
a=new StringBuffer("");
但是稳诚,執(zhí)行如下語句則可以通過編譯:
a.append(" broken!");
有人在定義方法的參數(shù)時哗脖,可能想采用如下形式來阻止方法內(nèi)部修改傳進(jìn)來的參數(shù)對象:
public void method(final ?StringBuffer param){
}
實際上,這是辦不到的扳还,在該方法內(nèi)部仍然可以增加如下代碼來修改參數(shù)對象:
param.append("a");
11才避、"=="和equals方法究竟有什么區(qū)別?
(單獨把一個東西說清楚氨距,然后再說清楚另一個桑逝,這樣,它們的區(qū)別自然就出來了俏让,混在一起說楞遏,則很難說清楚)
==操作符專門用來比較兩個變量的值是否相等茬暇,也就是用于比較變量所對應(yīng)的內(nèi)存中所存儲的數(shù)值是否相同,要比較兩個基本類型的數(shù)據(jù)或兩個引用變量是否相等寡喝,只能用==操作符糙俗。
如果一個變量指向的數(shù)據(jù)是對象類型的,那么预鬓,這時候涉及了兩塊內(nèi)存巧骚,對象本身占用一塊內(nèi)存(堆內(nèi)存),變量也占用一塊內(nèi)存格二,例如Objet obj = new Object();變量obj是一個內(nèi)存劈彪,new Object()是另一個內(nèi)存,此時顶猜,變量obj所對應(yīng)的內(nèi)存中存儲的數(shù)值就是對象占用的那塊內(nèi)存的首地址粉臊。對于指向?qū)ο箢愋偷淖兞浚绻容^兩個變量是否指向同一個對象驶兜,即要看這兩個變量所對應(yīng)的內(nèi)存中的數(shù)值是否相等,這時候就需要用==操作符進(jìn)行比較远寸。
equals方法是用于比較兩個獨立對象的內(nèi)容是否相同抄淑,就好比去比較兩個人的長相是否相同,它比較的兩個對象是獨立的驰后。例如肆资,對于下面的代碼:
String a=new String("foo");
String b=new String("foo");
兩條new語句創(chuàng)建了兩個對象,然后用a/b這兩個變量分別指向了其中一個對象灶芝,這是兩個不同的對象郑原,它們的首地址是不同的,即a和b中存儲的數(shù)值是不相同的夜涕,所以犯犁,表達(dá)式a==b將返回false,而這兩個對象中的內(nèi)容是相同的女器,所以酸役,表達(dá)式a.equals(b)將返回true。
在實際開發(fā)中驾胆,我們經(jīng)常要比較傳遞進(jìn)行來的字符串內(nèi)容是否等涣澡,例如,String input = …;input.equals(“quit”)丧诺,許多人稍不注意就使用==進(jìn)行比較了入桂,這是錯誤的,隨便從網(wǎng)上找?guī)讉€項目實戰(zhàn)的教學(xué)視頻看看驳阎,里面就有大量這樣的錯誤抗愁。記住馁蒂,字符串的比較基本上都是使用equals方法。
如果一個類沒有自己定義equals方法,那么它將繼承Object類的equals方法,Object類的equals方法的實現(xiàn)代碼如下:
boolean equals(Object o){
return this==o;
}
這說明准谚,如果一個類沒有自己定義equals方法霎槐,它默認(rèn)的equals方法(從Object類繼承的)就是使用==操作符,也是在比較兩個變量指向的對象是否是同一對象戈锻,這時候使用equals和使用==會得到同樣的結(jié)果,如果比較的是兩個獨立的對象則總返回false。如果你編寫的類希望能夠比較該類創(chuàng)建的兩個實例對象的內(nèi)容是否相同倘潜,那么你必須覆蓋equals方法,由你自己寫代碼來決定在什么情況即可認(rèn)為兩個對象的內(nèi)容是相同的志于。
12涮因、靜態(tài)變量和實例變量的區(qū)別?
在語法定義上的區(qū)別:靜態(tài)變量前要加static關(guān)鍵字伺绽,而實例變量前則不加养泡。
在程序運(yùn)行時的區(qū)別:實例變量屬于某個對象的屬性,必須創(chuàng)建了實例對象奈应,其中的實例變量才會被分配空間澜掩,才能使用這個實例變量。靜態(tài)變量不屬于某個實例對象杖挣,而是屬于類肩榕,所以也稱為類變量,只要程序加載了類的字節(jié)碼惩妇,不用創(chuàng)建任何實例對象株汉,靜態(tài)變量就會被分配空間,靜態(tài)變量就可以被使用了歌殃∏锹瑁總之,實例變量必須創(chuàng)建對象后才可以通過這個對象來使用挺份,靜態(tài)變量則可以直接使用類名來引用褒翰。
例如,對于下面的程序匀泊,無論創(chuàng)建多少個實例對象优训,永遠(yuǎn)都只分配了一個staticVar變量,并且每創(chuàng)建一個實例對象各聘,這個staticVar就會加1揣非;但是,每創(chuàng)建一個實例對象躲因,就會分配一個instanceVar早敬,即可能分配多個instanceVar忌傻,并且每個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);
}
}
備注:這個解答除了說清楚兩者的區(qū)別外搞监,最后還用一個具體的應(yīng)用例子來說明兩者的差異水孩,體現(xiàn)了自己有很好的解說問題和設(shè)計案例的能力,思維敏捷琐驴,超過一般程序員俘种,有寫作能力!
13绝淡、是否可以從一個static方法內(nèi)部發(fā)出對非static方法的調(diào)用宙刘?
不可以。因為非static方法是要與對象關(guān)聯(lián)在一起的牢酵,必須創(chuàng)建一個對象后悬包,才可以在該對象上進(jìn)行方法調(diào)用,而static方法調(diào)用時不需要創(chuàng)建對象馍乙,可以直接調(diào)用布近。也就是說,當(dāng)一個static方法被調(diào)用時丝格,可能還沒有創(chuàng)建任何實例對象吊输,如果從一個static方法中發(fā)出對非static方法的調(diào)用加匈,那個非static方法是關(guān)聯(lián)到哪個對象上的呢裁奇?這個邏輯無法成立也祠,所以,一個static方法內(nèi)部發(fā)出對非static方法的調(diào)用琅束。
14、Integer與int的區(qū)別
int是java提供的8種原始數(shù)據(jù)類型之一算谈。Java為每個原始類型提供了封裝類涩禀,Integer是java為int提供的封裝類。int的默認(rèn)值為0然眼,而Integer的默認(rèn)值為null艾船,即Integer可以區(qū)分出未賦值和值為0的區(qū)別,int則無法表達(dá)出未賦值的情況高每,例如屿岂,要想表達(dá)出沒有參加考試和考試成績?yōu)?的區(qū)別,則只能使用Integer鲸匿。在JSP開發(fā)中爷怀,Integer的默認(rèn)為null,所以用el表達(dá)式在文本框中顯示時带欢,值為空白字符串运授,而int默認(rèn)的默認(rèn)值為0烤惊,所以用el表達(dá)式在文本框中顯示時,結(jié)果為0吁朦,所以柒室,int不適合作為web層的表單數(shù)據(jù)的類型。
在Hibernate中逗宜,如果將OID定義為Integer類型雄右,那么Hibernate就可以根據(jù)其值是否為null而判斷一個對象是否是臨時的,如果將OID定義為了int類型锦溪,還需要在hbm映射文件中設(shè)置其unsaved-value屬性為0不脯。
另外,Integer提供了多個與整數(shù)相關(guān)的操作方法刻诊,例如防楷,將一個字符串轉(zhuǎn)換成整數(shù),Integer中還定義了表示整數(shù)的最大值和最小值的常量则涯。
15复局、Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math類中提供了三個與取整有關(guān)的方法:ceil、floor粟判、round亿昏,這些方法的作用與它們的英文名稱的含義相對應(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、下面的代碼有什么不妥之處?
1. if(username.equals(“zxx”){}
username可能為NULL,會報空指針錯誤而芥;改為"zxx".equals(username)
2.intx = 1;
return x==1?true:false; ?這個改成return x==1;就可以!
17涛贯、請說出作用域public垦沉,private枕稀,protected射亏,以及不寫時的區(qū)別
這四個作用域的可見范圍如下表所示莽红。
說明:如果在修飾的元素上面沒有寫任何訪問修飾符,則表示friendly稀余。
作用域 ? ?當(dāng)前類同一package子孫類其他package
public ? ?√ ? ?√ ? ? ? ? √ ? ? ?√
protected ?√ ? ?√ ? ? ? ? √ ? ? ×
friendly ? √ ? ?√ ? ? ? ? × ? ? ×
private ? ?√ ? ?× ? ? ? ? × ? ? ×
備注:只要記住了有4種訪問權(quán)限悦冀,4個訪問范圍,然后將全選和范圍在水平和垂直方向上分別按排從小到大或從大到小的順序排列睛琳,就很容易畫出上面的圖了盒蟆。
18、Overload和Override的區(qū)別师骗。Overloaded的方法是否可以改變返回值的類型?
Overload是重載的意思历等,Override是覆蓋的意思,也就是重寫辟癌。
重載Overload表示同一個類中可以有多個名稱相同的方法寒屯,但這些方法的參數(shù)列表各不相同(即參數(shù)個數(shù)或類型不同)。
重寫Override表示子類中的方法可以與父類中的某個方法的名稱和參數(shù)完全相同黍少,通過子類創(chuàng)建的實例對象調(diào)用這個方法時寡夹,將調(diào)用子類中的定義方法,這相當(dāng)于把父類中定義的那個完全相同的方法給覆蓋了厂置,這也是面向?qū)ο缶幊痰亩鄳B(tài)性的一種表現(xiàn)菩掏。子類覆蓋父類的方法時,只能比父類拋出更少的異常昵济,或者是拋出父類拋出的異常的子異常智绸,因為子類可以解決父類的一些問題,不能比父類有更多的問題访忿。子類方法的訪問權(quán)限只能比父類的更大传于,不能更小。如果父類的方法是private類型醉顽,那么,子類則不存在覆蓋的限制平挑,相當(dāng)于子類中增加了一個全新的方法游添。
至于Overloaded的方法是否可以改變返回值的類型這個問題,要看你倒底想問什么呢通熄?這個題目很模糊唆涝。如果幾個Overloaded的方法的參數(shù)列表不一樣,它們的返回者類型當(dāng)然也可以不一樣唇辨。但我估計你想問的問題是:如果兩個方法的參數(shù)列表完全一樣廊酣,是否可以讓它們的返回值不同來實現(xiàn)重載Overload。這是不行的赏枚,我們可以用反證法來說明這個問題亡驰,因為我們有時候調(diào)用一個方法時也可以不定義返回結(jié)果變量晓猛,即不要關(guān)心其返回結(jié)果,例如凡辱,我們調(diào)用map.remove(key)方法時戒职,雖然remove方法有返回值,但是我們通常都不會定義接收返回結(jié)果的變量透乾,這時候假設(shè)該類中有兩個名稱和參數(shù)列表完全相同的方法洪燥,僅僅是返回類型不同,java就無法確定編程者倒底是想調(diào)用哪個方法了乳乌,因為它無法通過返回結(jié)果類型來判斷捧韵。
override可以翻譯為覆蓋,從字面就可以知道汉操,它是覆蓋了一個方法并且對其重寫再来,以求達(dá)到不同的作用。對我們來說最熟悉的覆蓋就是對接口方法的實現(xiàn)客情,在接口中一般只是對方法進(jìn)行了聲明其弊,而我們在實現(xiàn)時几蜻,就需要實現(xiàn)接口聲明的所有方法慎颗。除了這個典型的用法以外速缆,我們在繼承中也可能會在子類覆蓋父類中的方法草姻。在覆蓋要注意以下的幾點:
1骂铁、覆蓋的方法的標(biāo)志必須要和被覆蓋的方法的標(biāo)志完全匹配咱娶,才能達(dá)到覆蓋的效果彩倚;
2堵未、覆蓋的方法的返回值必須和被覆蓋的方法的返回一致摔蓝;
3赂苗、覆蓋的方法所拋出的異常必須和被覆蓋方法的所拋出的異常一致,或者是其子類贮尉;
4拌滋、被覆蓋的方法不能為private,否則在其子類中只是新定義了一個方法猜谚,并沒有對其進(jìn)行覆蓋败砂。
overload對我們來說可能比較熟悉,可以翻譯為重載魏铅,它是指我們可以定義一些名稱相同的方法昌犹,通過定義不同的輸入?yún)?shù)來區(qū)分這些方法,然后再調(diào)用時览芳,VM就會根據(jù)不同的參數(shù)樣式斜姥,來選擇合適的方法執(zhí)行。在使用重載要注意以下的幾點:
1、在使用重載時只能通過不同的參數(shù)樣式铸敏。例如缚忧,不同的參數(shù)類型,不同的參數(shù)個數(shù)搞坝,不同的參數(shù)順序(當(dāng)然搔谴,同一方法內(nèi)的幾個參數(shù)類型必須不一樣,例如可以是fun(int,float)桩撮,但是不能為fun(int,int))敦第;
2、不能通過訪問權(quán)限店量、返回類型芜果、拋出的異常進(jìn)行重載;
3融师、方法的異常類型和數(shù)目不會對重載造成影響右钾;
4、對于繼承來說旱爆,如果某一方法在父類中是訪問權(quán)限是priavte舀射,那么就不能在子類對其進(jìn)行重載,如果定義的話怀伦,也只是定義了一個新方法脆烟,而不會達(dá)到重載的效果。
19房待、構(gòu)造器Constructor是否可被override?
構(gòu)造器Constructor不能被繼承邢羔,因此不能重寫Override,但可以被重載Overload桑孩。
20拜鹤、接口是否可繼承接口?抽象類是否可實現(xiàn)(implements)接口?抽象類是否可繼承具體類(concrete class)?抽象類中是否可以有靜態(tài)的main方法?
接口可以繼承接口流椒。抽象類可以實現(xiàn)(implements)接口敏簿,抽象類可以繼承具體類。抽象類中可以有靜態(tài)的main方法宣虾。
備注:只要明白了接口和抽象類的本質(zhì)和作用惯裕,這些問題都很好回答,你想想,如果你是java語言的設(shè)計者,你是否會提供這樣的支持瘸爽,如果不提供的話播掷,有什么理由嗎?如果你沒有道理不提供,那答案就是肯定的了次员。
只有記住抽象類與普通類的唯一區(qū)別就是不能創(chuàng)建實例對象和允許有abstract方法败许。
21、寫clone()方法時淑蔚,通常都有一行代碼市殷,是什么?
clone 有缺省行為刹衫,super.clone();因為首先要把父類中的成員復(fù)制到位醋寝,然后才是復(fù)制自己的成員。
22带迟、面向?qū)ο蟮奶卣饔心男┓矫?/b>
計算機(jī)軟件系統(tǒng)是現(xiàn)實生活中的業(yè)務(wù)在計算機(jī)中的映射音羞,而現(xiàn)實生活中的業(yè)務(wù)其實就是一個個對象協(xié)作的過程。面向?qū)ο缶幊叹褪前船F(xiàn)實業(yè)務(wù)一樣的方式將程序代碼按一個個對象進(jìn)行組織和編寫仓犬,讓計算機(jī)系統(tǒng)能夠識別和理解用對象方式組織和編寫的程序代碼嗅绰,這樣就可以把現(xiàn)實生活中的業(yè)務(wù)對象映射到計算機(jī)系統(tǒng)中。
面向?qū)ο蟮木幊陶Z言有4個主要的特征搀继。
1封裝:
封裝是保證軟件部件具有優(yōu)良的模塊性的基礎(chǔ)窘面,封裝的目標(biāo)就是要實現(xiàn)軟件部件的“高內(nèi)聚、低耦合”叽躯,防止程序相互依賴性而帶來的變動影響财边。在面向?qū)ο蟮木幊陶Z言中,對象是封裝的最基本單位险毁,面向?qū)ο蟮姆庋b比傳統(tǒng)語言的封裝更為清晰制圈、更為有力。面向?qū)ο蟮姆庋b就是把描述一個對象的屬性和行為的代碼封裝在一個“模塊”中畔况,也就是一個類中鲸鹦,屬性用變量定義,行為用方法進(jìn)行定義跷跪,方法可以直接訪問同一個對象中的屬性馋嗜。通常情況下,只要記住讓變量和訪問這個變量的方法放在一起吵瞻,將一個類中的成員變量全部定義成私有的葛菇,只有這個類自己的方法才可以訪問到這些成員變量,這就基本上實現(xiàn)對象的封裝橡羞,就很容易找出要分配到這個類上的方法了眯停,就基本上算是會面向?qū)ο蟮木幊塘恕0盐找粋€原則:把對同一事物進(jìn)行操作的方法和相關(guān)的方法放在同一個類中卿泽,把方法和它操作的數(shù)據(jù)放在同一個類中莺债。
例如,人要在黑板上畫圓,這一共涉及三個對象:人齐邦、黑板椎侠、圓,畫圓的方法要分配給哪個對象呢措拇?由于畫圓需要使用到圓心和半徑我纪,圓心和半徑顯然是圓的屬性,如果將它們在類中定義成了私有的成員變量丐吓,那么浅悉,畫圓的方法必須分配給圓,它才能訪問到圓心和半徑這兩個屬性汰蜘,人以后只是調(diào)用圓的畫圓方法仇冯、表示給圓發(fā)給消息而已,畫圓這個方法不應(yīng)該分配在人這個對象上族操,這就是面向?qū)ο蟮姆庋b性苛坚,即將對象封裝成一個高度自治和相對封閉的個體葵陵,對象狀態(tài)(屬性)由這個對象自己的行為(方法)來讀取和改變腔彰。一個更便于理解的例子就是,司機(jī)將火車剎住了裕循,剎車的動作是分配給司機(jī)枷莉,還是分配給火車娇昙,顯然,應(yīng)該分配給火車笤妙,因為司機(jī)自身是不可能有那么大的力氣將一個火車給停下來的冒掌,只有火車自己才能完成這一動作,火車需要調(diào)用內(nèi)部的離合器和剎車片等多個器件協(xié)作才能完成剎車這個動作蹲盘,司機(jī)剎車的過程只是給火車發(fā)了一個消息股毫,通知火車要執(zhí)行剎車動作而已。
抽象:
抽象就是找出一些事物的相似和共性之處召衔,然后將這些事物歸為一個類铃诬,這個類只考慮這些事物的相似和共性之處,并且會忽略與當(dāng)前主題和目標(biāo)無關(guān)的那些方面苍凛,將注意力集中在與當(dāng)前目標(biāo)有關(guān)的方面趣席。例如,看到一只螞蟻和大象醇蝴,你能夠想象出它們的相同之處宣肚,那就是抽象。抽象包括行為抽象和狀態(tài)抽象兩個方面悠栓。例如霉涨,定義一個Person類弧呐,如下:
Class Person{
String name;
int age;
}
人本來是很復(fù)雜的事物,有很多方面嵌纲,但因為當(dāng)前系統(tǒng)只需要了解人的姓名和年齡,所以上面定義的類中只包含姓名和年齡這兩個屬性腥沽,這就是一種抽像逮走,使用抽象可以避免考慮一些與目標(biāo)無關(guān)的細(xì)節(jié)。我對抽象的理解就是不要用顯微鏡去看一個事物的所有方面今阳,這樣涉及的內(nèi)容就太多了师溅,而是要善于劃分問題的邊界,當(dāng)前系統(tǒng)需要什么盾舌,就只考慮什么墓臭。
繼承:
在定義和實現(xiàn)一個類的時候,可以在一個已經(jīng)存在的類的基礎(chǔ)之上來進(jìn)行妖谴,把這個已經(jīng)存在的類所定義的內(nèi)容作為自己的內(nèi)容窿锉,并可以加入若干新的內(nèi)容,或修改原來的方法使之更適合特殊的需要膝舅,這就是繼承嗡载。繼承是子類自動共享父類數(shù)據(jù)和方法的機(jī)制,這是類之間的一種關(guān)系仍稀,提高了軟件的可重用性和可擴(kuò)展性洼滚。
多態(tài):
多態(tài)是指程序中定義的引用變量所指向的具體類型和通過該引用變量發(fā)出的方法調(diào)用在編程時并不確定,而是在程序運(yùn)行期間才確定技潘,即一個引用變量倒底會指向哪個類的實例對象遥巴,該引用變量發(fā)出的方法調(diào)用到底是哪個類中實現(xiàn)的方法,必須在由程序運(yùn)行期間才能決定享幽。因為在程序運(yùn)行時才確定具體的類铲掐,這樣,不用修改源程序代碼琉闪,就可以讓引用變量綁定到各種不同的類實現(xiàn)上迹炼,從而導(dǎo)致該引用調(diào)用的具體方法隨之改變,即不修改程序代碼就可以改變程序運(yùn)行時所綁定的具體代碼颠毙,讓程序可以選擇多個運(yùn)行狀態(tài)斯入,這就是多態(tài)性。多態(tài)性增強(qiáng)了軟件的靈活性和擴(kuò)展性蛀蜜。例如犹菇,下面代碼中的UserDao是一個接口殴玛,它定義引用變量userDao指向的實例對象由daofactory.getDao()在執(zhí)行的時候返回,有時候指向的是UserJdbcDao這個實現(xiàn)港柜,有時候指向的是UserHibernateDao這個實現(xiàn),這樣材义,不用修改源代碼,就可以改變userDao指向的具體類實現(xiàn),從而導(dǎo)致userDao.insertUser()方法調(diào)用的具體代碼也隨之改變饼灿,即有時候調(diào)用的是UserJdbcDao的insertUser方法,有時候調(diào)用的是UserHibernateDao的insertUser方法:
UserDao userDao =daofactory.getDao();
userDao.insertUser(user);
比喻:人吃飯帝美,你看到的是左手碍彭,還是右手?
23悼潭、java中實現(xiàn)多態(tài)的機(jī)制是什么庇忌?
靠的是父類或接口定義的引用變量可以指向子類或具體實現(xiàn)類的實例對象,而程序調(diào)用的方法在運(yùn)行期才動態(tài)綁定舰褪,就是引用變量所指向的具體實例對象的方法皆疹,也就是內(nèi)存里正在運(yùn)行的那個對象的方法,而不是引用變量的類型中定義的方法占拍。
24略就、abstract class和interface有什么區(qū)別?
含有abstract修飾符的class即為抽象類,abstract類不能創(chuàng)建實例對象晃酒。含有abstract方法的類必須定義為abstract class残制,abstract class類中的方法不必是抽象的。abstract class類中定義抽象方法必須在具體(Concrete)子類中實現(xiàn)掖疮,所以初茶,不能有抽象構(gòu)造方法或抽象靜態(tài)方法。如果的子類沒有實現(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)類型,雖然
eclipse下不報錯何什,但應(yīng)該也不行),但接口中的抽象方法只能是public類型的等龙,并且默認(rèn)即為public abstract類型处渣。
5.抽象類中可以包含靜態(tài)方法伶贰,接口中不能包含靜態(tài)方法
6.抽象類和接口中都可以包含靜態(tài)成員變量,抽象類中的靜態(tài)成員變量的訪問類型可以任意罐栈,但接口中定義的變量只能是public static final類型黍衙,并且默認(rèn)即為public static final類型。
7. 一個類可以實現(xiàn)多個接口荠诬,但只能繼承一個抽象類们豌。
下面接著再說說兩者在應(yīng)用上的區(qū)別:
接口更多的是在系統(tǒng)架構(gòu)設(shè)計方法發(fā)揮作用,主要用于定義模塊之間的通信契約浅妆。而抽象類在代碼實現(xiàn)方面發(fā)揮作用,可以實現(xiàn)代碼的重用障癌,例如凌外,模板方法設(shè)計模式是抽象類的一個典型應(yīng)用,假設(shè)某個項目的所有Servlet類都要用相同的方式進(jìn)行權(quán)限判斷涛浙、記錄訪問日志和處理異常,那么就可以定義一個抽象的基類,讓所有的Servlet都繼承這個抽象基類齐饮,在抽象基類的service方法中完成權(quán)限判斷姿搜、記錄訪問日志和處理異常的代碼,在各個子類中只是完成各自的業(yè)務(wù)邏輯代碼我注,偽代碼如下:
public abstract classBaseServlet extends HttpServlet{
public final 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)但骨,因為它是專門給子類用的
}
public class MyServlet1 extendsBaseServlet
{
protected voiddoService(HttpServletRequest request, HttpServletResponse response) throwsIOExcetion,ServletException
{
本Servlet只處理的具體業(yè)務(wù)邏輯代碼
}
}
父類方法中間的某段代碼不確定励七,留給子類干,就用模板方法設(shè)計模式奔缠。
備注:這道題的思路是先從總體解釋抽象類和接口的基本概念掠抬,然后再比較兩者的語法細(xì)節(jié),最后再說兩者的應(yīng)用區(qū)別校哎。比較兩者語法細(xì)節(jié)區(qū)別的條理是:先從一個類中的構(gòu)造方法两波、普通成員變量和方法(包括抽象方法),靜態(tài)變量和方法闷哆,繼承性等6個方面逐一去比較回答腰奋,接著從第三者繼承的角度的回答,特別是最后用了一個典型的例子來展現(xiàn)自己深厚的技術(shù)功底抱怔。
25氛堕、abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized?
abstract的method不可以是static的野蝇,因為抽象的方法是要被子類實現(xiàn)的讼稚,而static與子類扯不上關(guān)系括儒!
native方法表示該方法要用另外一種依賴平臺的編程語言實現(xiàn)的,不存在著被子類實現(xiàn)的問題锐想,所以帮寻,它也不能是抽象的,不能與abstract混用赠摇。例如固逗,F(xiàn)ileOutputSteam類要硬件打交道,底層的實現(xiàn)用的是操作系統(tǒng)相關(guān)的api實現(xiàn)藕帜,例如烫罩,在windows用c語言實現(xiàn)的,所以洽故,查看jdk的源代碼贝攒,可以發(fā)現(xiàn)FileOutputStream的open方法的定義如下:
private native void open(Stringname) throws FileNotFoundException;
如果我們要用java調(diào)用別人寫的c語言函數(shù),我們是無法直接調(diào)用的时甚,我們需要按照java的要求寫一個c語言的函數(shù)隘弊,又我們的這個c語言函數(shù)去調(diào)用別人的c語言函數(shù)。由于我們的c語言函數(shù)是按java的要求來寫的荒适,我們這個c語言函數(shù)就可以與java對接上梨熙,java那邊的對接方式就是定義出與我們這個c函數(shù)相對應(yīng)的方法,java中對應(yīng)的方法不需要寫具體的代碼刀诬,但需要在前面聲明native咽扇。
關(guān)于synchronized與abstract合用的問題,我覺得也不行陕壹,因為在我?guī)啄甑膶W(xué)習(xí)和開發(fā)中肌割,從來沒見到過這種情況,并且我覺得synchronized應(yīng)該是作用在一個具體的方法上才有意義帐要。而且把敞,方法上的synchronized同步所使用的同步鎖對象是this,而抽象方法上無法確定this是什么榨惠。
26奋早、什么是內(nèi)部類?Static Nested Class和Inner Class的不同赠橙。
內(nèi)部類就是在一個類的內(nèi)部定義的類耽装,內(nèi)部類中不能定義靜態(tài)成員(靜態(tài)成員不是對象的特性,只是為了找一個容身之處,所以需要放到一個類中而已,這么一點小事欢峰,你還要把它放到類內(nèi)部的一個類中淮椰,過分了啊晋柱!提供內(nèi)部類洒沦,不是為讓你干這種事情赁温,無聊速兔,不讓你干墅拭。我想可能是既然靜態(tài)成員類似c語言的全局變量,而內(nèi)部類通常是用于創(chuàng)建內(nèi)部對象用的涣狗,所以谍婉,把“全局變量”放在內(nèi)部類中就是毫無意義的事情,既然是毫無意義的事情镀钓,就應(yīng)該被禁止)穗熬,內(nèi)部類可以直接訪問外部類中的成員變量,內(nèi)部類可以定義在外部類的方法外面丁溅,也可以定義在外部類的方法體中唤蔗,如下所示:
public class Outer
{
int out_x ?= 0;
public void method()
{
Inner1 inner1 = new Inner1();
public 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種訪問類型一樣,它們決定這個內(nèi)部類的定義對其他類是否可見别凤;對于這種情況饰序,我們也可以在外面創(chuàng)建內(nèi)部類的實例對象,創(chuàng)建內(nèi)部類的實例對象時规哪,一定要先創(chuàng)建外部類的實例對象求豫,然后用這個外部類的實例對象去創(chuàng)建內(nèi)部類的實例對象,代碼如下:
Outer outer = new Outer();
Outer.Inner1 inner1 = outer.new Innner1();
在方法內(nèi)部定義的內(nèi)部類前面不能有訪問類型修飾符诉稍,就好像方法中定義的局部變量一樣蝠嘉,但這種內(nèi)部類的前面可以使用final或abstract修飾符。這種內(nèi)部類對其他類是不可見的其他類無法引用這種內(nèi)部類杯巨,但是這種內(nèi)部類創(chuàng)建的實例對象可以傳遞給其他類訪問蚤告。這種內(nèi)部類必須是先定義,后使用服爷,即內(nèi)部類的定義代碼必須出現(xiàn)在使用該類之前杜恰,這與方法中的局部變量必須先定義后使用的道理也是一樣的。這種內(nèi)部類可以訪問方法體中的局部變量仍源,但是心褐,該局部變量前必須加final修飾符。
對于這些細(xì)節(jié)笼踩,只要在eclipse寫代碼試試逗爹,根據(jù)開發(fā)工具提示的各類錯誤信息就可以馬上了解到。
在方法體內(nèi)部還可以采用如下語法來創(chuàng)建一種匿名內(nèi)部類嚎于,即定義某一接口或類的子類的同時掘而,還創(chuàng)建了該子類的實例對象挟冠,無需為該子類定義名稱:
public class Outer
{
public void start()
{
new Thread(
new Runable(){
public void run(){};
}
).start();
}
}
最后,在方法外部定義的內(nèi)部類前面可以加上static關(guān)鍵字镣屹,從而成為Static Nested Class圃郊,它不再具有內(nèi)部類的特性,所有女蜈,從狹義上講持舆,它不是內(nèi)部類。Static Nested Class與普通類在運(yùn)行時的行為和功能上沒有什么區(qū)別伪窖,只是在編程引用時的語法上有一些差別逸寓,它可以定義成public、protected覆山、默認(rèn)的竹伸、private等多種類型,而普通類只能定義成public和默認(rèn)的這兩種類型簇宽。在外面引用Static Nested Class類的名稱為“外部類名.內(nèi)部類名”母截。在外面不需要創(chuàng)建外部類的實例對象,就可以直接創(chuàng)建Static Nested Class鸡挠,例如滑进,假設(shè)Inner是定義在Outer類中的Static Nested Class,那么可以使用如下語句創(chuàng)建Inner類:
Outer.Inner inner = new Outer.Inner();
由于static Nested Class不依賴于外部類的實例對象钞它,所以拜银,static Nested Class能訪問外部類的非static成員變量(不能直接訪問,需要創(chuàng)建外部類實例才能訪問非靜態(tài)變量)遭垛。當(dāng)在外部類中訪問Static Nested Class時尼桶,可以直接使用Static Nested Class的名字,而不需要加上外部類的名字了锯仪,在Static Nested Class中也可以直接引用外部類的static的成員變量泵督,不需要加上外部類的名字。
在靜態(tài)方法中定義的內(nèi)部類也是Static Nested Class庶喜,這時候不能在類前面加static關(guān)鍵字幌蚊,靜態(tài)方法中的Static Nested Class與普通方法中的內(nèi)部類的應(yīng)用方式很相似,它除了可以直接訪問外部類中的static的成員變量溃卡,還可以訪問靜態(tài)方法中的局部變量溢豆,但是,該局部變量前必須加final修飾符瘸羡。
備注:首先根據(jù)你的印象說出你對內(nèi)部類的總體方面的特點:例如漩仙,在兩個地方可以定義,可以訪問外部類的成員變量,不能定義靜態(tài)成員队他,這是大的特點卷仑。然后再說一些細(xì)節(jié)方面的知識,例如麸折,幾種定義方式的語法區(qū)別锡凝,靜態(tài)內(nèi)部類,以及匿名內(nèi)部類垢啼。
27窜锯、內(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)部類不能訪問外部類的成員,但你一上來就頂牛掉分,這不好俭缓,要先順著人家克伊,讓人家滿意酥郭,然后再說特殊情況,讓人家吃驚愿吹。
28不从、Anonymous Inner Class (匿名內(nèi)部類)是否可以extends(繼承)其它類,是否可以implements(實現(xiàn))interface(接口)?
可以繼承其他類或?qū)崿F(xiàn)其他接口犁跪。不僅是可以椿息,而是必須!
29、super.getClass()方法調(diào)用
下面程序的輸出結(jié)果是多少坷衍?
Import java.util.Date;
publicclassTestextendsDate{
public static voidmain(String[] args) {
newTest().test();
}
public voidtest(){
System.out.println(super.getClass().getName());
}
}
很奇怪寝优,結(jié)果是Test
這屬于腦筋急轉(zhuǎn)彎的題目,在一個qq群有個網(wǎng)友正好問過這個問題枫耳,我覺得挺有趣,就研究了一下,沒想到今天還被你面到了疫诽,哈哈。
在test方法中凄硼,直接調(diào)用getClass().getName()方法,返回的是Test類名
由于getClass()在Object類中定義成了final捷沸,子類不能覆蓋該方法摊沉,所以,在
test方法中調(diào)用getClass().getName()方法痒给,其實就是在調(diào)用從父類繼承的getClass()方法说墨,等效于調(diào)用super.getClass().getName()方法,所以侈玄,super.getClass().getName()方法返回的也應(yīng)該是Test婉刀。
如果想得到父類的名稱,應(yīng)該用如下代碼:
getClass().getSuperClass().getName();
30序仙、String是最基本的數(shù)據(jù)類型嗎?
基本數(shù)據(jù)類型包括byte突颊、int、char潘悼、long律秃、float、double治唤、boolean和short棒动。
java.lang.String類是final類型的,因此不可以繼承這個類宾添、不能修改這個類船惨。為了提高效率節(jié)省空間,我們應(yīng)該用StringBuffer類
31缕陕、String s = "Hello";s = s + " world!";這兩行代碼執(zhí)行后粱锐,原始的String對象中的內(nèi)容到底變了沒有?
沒有扛邑。因為String被設(shè)計成不可變(immutable)類怜浅,所以它的所有對象都是不可變對象。在這段代碼中蔬崩,s原先指向一個String對象恶座,內(nèi)容是 "Hello",然后我們對s進(jìn)行了+操作沥阳,那么s所指向的那個對象是否發(fā)生了改變呢跨琳?答案是沒有。這時桐罕,s不指向原來那個對象了脉让,而指向了另一個 String對象樟氢,內(nèi)容為"Hello world!",原來那個對象還存在于內(nèi)存之中侠鳄,只是s這個引用變量不再指向它了埠啃。
通過上面的說明,我們很容易導(dǎo)出另一個結(jié)論伟恶,如果經(jīng)常對字符串進(jìn)行各種各樣的修改碴开,或者說,不可預(yù)見的修改博秫,那么使用String來代表字符串的話會引起很大的內(nèi)存開銷潦牛。因為 String對象建立之后不能再改變,所以對于每一個不同的字符串挡育,都需要一個String對象來表示巴碗。這時,應(yīng)該考慮使用StringBuffer類即寒,它允許修改橡淆,而不是每個不同的字符串都要生成一個新的對象。并且母赵,這兩種類的對象轉(zhuǎn)換十分容易逸爵。
同時找筝,我們還可以知道赛糟,如果要使用內(nèi)容相同的字符串办桨,不必每次都new一個String事扭。例如我們要在構(gòu)造器中對一個名叫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");
后者每次都會調(diào)用構(gòu)造器枢泰,生成新對象笨蚁,性能低下且內(nèi)存開銷大凶朗,并且沒有意義瓷胧,因為String對象不可改變,所以對于內(nèi)容相同的字符串俱尼,只要一個String對象來表示就可以了抖单。也就說萎攒,多次調(diào)用上面的構(gòu)造器創(chuàng)建多個對象遇八,他們的String類型屬性s都指向同一個對象。
上面的結(jié)論還基于這樣一個事實:對于字符串常量耍休,如果內(nèi)容相同刃永,Java認(rèn)為它們代表同一個String對象。而用關(guān)鍵字new調(diào)用構(gòu)造器羊精,總是會創(chuàng)建一個新的對象斯够,無論內(nèi)容是否相同囚玫。
至于為什么要把String類設(shè)計成不可變類,是它的用途決定的读规。其實不只String抓督,很多Java標(biāo)準(zhǔn)類庫中的類都是不可變的。在開發(fā)一個系統(tǒng)的時候束亏,我們有時候也需要設(shè)計不可變類铃在,來傳遞一組相關(guān)的值,這也是面向?qū)ο笏枷氲捏w現(xiàn)碍遍。不可變類有一些優(yōu)點定铜,比如因為它的對象是只讀的,所以多線程并發(fā)訪問也不會有任何問題怕敬。當(dāng)然也有一些缺點揣炕,比如每個不同的狀態(tài)都要一個對象來代表,可能會造成性能上的問題东跪。所以Java標(biāo)準(zhǔn)類庫還提供了一個可變版本畸陡,即 StringBuffer。
32虽填、是否可以繼承String類?
String類是final類故不可以繼承罩锐。
33、String s = new String("xyz");創(chuàng)建了幾個String Object?二者之間有什么區(qū)別卤唉?
兩個或一個涩惑,”xyz”對應(yīng)一個對象,這個對象放在字符串常量緩沖區(qū)桑驱,常量”xyz”不管出現(xiàn)多少遍竭恬,都是緩沖區(qū)中的那一個。New String每寫一遍熬的,就創(chuàng)建一個新的對象痊硕,它一句那個常量”xyz”對象的內(nèi)容來創(chuàng)建出一個新String對象。如果以前就用過’xyz’押框,這句代表就不會創(chuàng)建”xyz”自己了岔绸,直接從緩沖區(qū)拿。
34橡伞、String和StringBuffer的區(qū)別
JAVA平臺提供了兩個類:String和StringBuffer盒揉,它們可以儲存和操作字符串,即包含多個字符的字符數(shù)據(jù)兑徘。這個String類提供了數(shù)值不可改變的字符串刚盈。而這個StringBuffer類提供的字符串進(jìn)行修改。當(dāng)你知道字符數(shù)據(jù)要改變的時候你就可以使用StringBuffer挂脑。典型地酪我,你可以使用StringBuffers來動態(tài)構(gòu)造字符數(shù)據(jù)。另外疫粥,String實現(xiàn)了equals方法,new String(“abc”).equals(newString(“abc”)的結(jié)果為true,而StringBuffer沒有實現(xiàn)equals方法威蕉,所以,new StringBuffer(“abc”).equals(newStringBuffer(“abc”)的結(jié)果為false橄仍。
接著要舉一個具體的例子來說明忘伞,我們要把1到100的所有數(shù)字拼起來,組成一個串沙兰。
StringBuffer sbf = new StringBuffer();
for(int i=0;i<100;i++)
{
sbf.append(i);
}
上面的代碼效率很高氓奈,因為只創(chuàng)建了一個StringBuffer對象,而下面的代碼效率很低鼎天,因為創(chuàng)建了101個對象舀奶。
String str = new String();
for(int i=0;i<100;i++)
{
str = str + i;
}
在講兩者區(qū)別時,應(yīng)把循環(huán)的次數(shù)搞成10000斋射,然后用endTime-beginTime來比較兩者執(zhí)行的時間差異育勺,最后還要講講StringBuilder與StringBuffer的區(qū)別。
String覆蓋了equals方法和hashCode方法罗岖,而StringBuffer沒有覆蓋equals方法和hashCode方法涧至,所以,將StringBuffer對象存儲進(jìn)Java集合類中時會出現(xiàn)問題桑包。
35南蓬、如何把一段逗號分割的字符串轉(zhuǎn)換成一個數(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();
}
36、數(shù)組有沒有l(wèi)ength()這個方法? String有沒有l(wèi)ength()這個方法弱左?
數(shù)組沒有l(wèi)ength()這個方法窄陡,有l(wèi)ength的屬性。String有有l(wèi)ength()這個方法拆火。
37跳夭、下面這條語句一共創(chuàng)建了多少個對象:String s="a"+"b"+"c"+"d";
答:對于如下代碼:
String s1 = "a";
String s2 = s1 + "b";
String s3 = "a" + "b";
System.out.println(s2 == "ab");
System.out.println(s3 == "ab");
第一條語句打印的結(jié)果為false,第二條語句打印的結(jié)果為true们镜,這說明javac編譯可以對字符串常量直接相加的表達(dá)式進(jìn)行優(yōu)化币叹,不必要等到運(yùn)行期去進(jìn)行加法運(yùn)算處理,而是在編譯時去掉其中的加號憎账,直接將其編譯成一個這些常量相連的結(jié)果套硼。
題目中的第一行代碼被編譯器在編譯時優(yōu)化后卡辰,相當(dāng)于直接定義了一個”abcd”的字符串胞皱,所以邪意,上面的代碼應(yīng)該只創(chuàng)建了一個String對象。寫如下兩行代碼反砌,
String s ="a" + "b" + "c" + "d";
System.out.println(s== "abcd");
最終打印的結(jié)果應(yīng)該為true雾鬼。
38、try {}里有一個return語句宴树,那么緊跟在這個try后的finally {}里的code會不會被執(zhí)行策菜,什么時候被執(zhí)行,在return前還是后?
也許你的答案是在return之前酒贬,但往更細(xì)地說又憨,我的答案是在return中間執(zhí)行,請看下面程序代碼的運(yùn)行結(jié)果:
publicclassTest {
/**
*@paramargs add by zxx ,Dec 9, 2008
*/
public static voidmain(String[] args) {
//TODOAuto-generated method stub
System.out.println(newTest().test());;
}
staticinttest()
{
intx = 1;
try
{
returnx;
}
finally
{
++x;
}
}
}
---------執(zhí)行結(jié)果 ---------
1
運(yùn)行結(jié)果是1锭吨,為什么呢蠢莺?主函數(shù)調(diào)用子函數(shù)并得到結(jié)果的過程,好比主函數(shù)準(zhǔn)備一個空罐子零如,當(dāng)子函數(shù)要返回結(jié)果時躏将,先把結(jié)果放在罐子里,然后再將程序邏輯返回到主函數(shù)考蕾。所謂返回祸憋,就是子函數(shù)說,我不運(yùn)行了,你主函數(shù)繼續(xù)運(yùn)行吧研乒,這沒什么結(jié)果可言痊土,結(jié)果是在說這話之前放進(jìn)罐子里的。
39沟沙、下面的程序代碼輸出的結(jié)果是多少?
public classsmallT
{
public staticvoid ?main(String args[])
{
smallT t ?= new smallT();
int ?b = ?t.get();
System.out.println(b);
}
public int ?get()
{
try
{
return1 ;
}
finally
{
return2 ;
}
}
}
返回的結(jié)果是2壁榕。
我可以通過下面一個例子程序來幫助我解釋這個答案矛紫,從下面例子的運(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ù)并不是馬上返回,它要執(zhí)行finally語句后才真正開始返回奏黑。
在講解答案時可以用下面的程序來幫助分析:
publicclassTest {
/**
*@paramargs add by zxx ,Dec 9, 2008
*/
public static voidmain(String[] args) {
//TODOAuto-generated method stub
System.out.println(newTest().test());;
}
inttest()
{
try
{
returnfunc1();
}
finally
{
returnfunc2();
}
}
intfunc1()
{
System.out.println("func1");
return1;
}
intfunc2()
{
System.out.println("func2");
return2;
}
}
-----------執(zhí)行結(jié)果-----------------
func1
func2
2
結(jié)論:finally中的代碼比return和break語句后執(zhí)行
40炊邦、final, finally, finalize的區(qū)別编矾。
final 用于聲明屬性,方法和類馁害,分別表示屬性不可變窄俏,方法不可覆蓋,類不可繼承碘菜。
內(nèi)部類要訪問局部變量凹蜈,局部變量必須定義成final類型,例如忍啸,一段代碼……
finally是異常處理語句結(jié)構(gòu)的一部分仰坦,表示總是執(zhí)行。
finalize是Object類的一個方法计雌,在垃圾收集器執(zhí)行的時候會調(diào)用被回收對象的此方法缎岗,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關(guān)閉文件等白粉。JVM不保證此方法總被調(diào)用
41传泊、運(yùn)行時異常與一般異常有何異同?
異常表示程序運(yùn)行過程中可能出現(xiàn)的非正常狀態(tài)鸭巴,運(yùn)行時異常表示虛擬機(jī)的通常操作中可能遇到的異常眷细,是一種常見運(yùn)行錯誤。java編譯器要求方法必須聲明拋出可能發(fā)生的非運(yùn)行時異常鹃祖,但是并不要求必須聲明拋出未被捕獲的運(yùn)行時異常溪椎。
42、error和exception有什么區(qū)別?
error 表示恢復(fù)不是不可能但很困難的情況下的一種嚴(yán)重問題恬口。比如說內(nèi)存溢出校读。不可能指望程序能處理這樣的情況。 exception表示一種設(shè)計或?qū)崿F(xiàn)問題祖能。也就是說歉秫,它表示如果程序運(yùn)行正常,從不會發(fā)生的情況养铸。
43雁芙、Java中的異常處理機(jī)制的簡單原理和應(yīng)用。
異常是指java程序運(yùn)行時(非編譯)所發(fā)生的非正常情況或錯誤钞螟,與現(xiàn)實生活中的事件很相似兔甘,現(xiàn)實生活中的事件可以包含事件發(fā)生的時間、地點鳞滨、人物洞焙、情節(jié)等信息,可以用一個對象來表示,Java使用面向?qū)ο蟮姆绞絹硖幚懋惓T璺耍殉绦蛑邪l(fā)生的每個異常也都分別封裝到一個對象來表示的熔任,該對象中包含有異常的信息显晶。
Java對異常進(jìn)行了分類,不同類型的異常分別用不同的Java類表示敢靡,所有異常的根類為java.lang.Throwable断部,Throwable下面又派生了兩個子類:Error和Exception,Error表示應(yīng)用程序本身無法克服和恢復(fù)的一種嚴(yán)重問題贡蓖,程序只有死的份了,例如,說內(nèi)存溢出和線程死鎖等系統(tǒng)問題哀墓。Exception表示程序還能夠克服和恢復(fù)的問題,其中又分為系統(tǒng)異常和普通異常喷兼,系統(tǒng)異常是軟件本身缺陷所導(dǎo)致的問題篮绰,也就是軟件開發(fā)人員考慮不周所導(dǎo)致的問題,軟件使用者無法克服和恢復(fù)這種問題季惯,但在這種問題下還可以讓軟件系統(tǒng)繼續(xù)運(yùn)行或者讓軟件死掉吠各,例如,數(shù)組腳本越界(ArrayIndexOutOfBoundsException)勉抓,空指針異常(NullPointerException)贾漏、類轉(zhuǎn)換異常(ClassCastException);普通異常是運(yùn)行環(huán)境的變化或異常所導(dǎo)致的問題藕筋,是用戶能夠克服的問題纵散,例如,網(wǎng)絡(luò)斷線隐圾,硬盤空間不夠伍掀,發(fā)生這樣的異常后,程序不應(yīng)該死掉暇藏。
java為系統(tǒng)異常和普通異常提供了不同的解決方案蜜笤,編譯器強(qiáng)制普通異常必須try..catch處理或用throws聲明繼續(xù)拋給上層調(diào)用方法處理,所以普通異常也稱為checked異常盐碱,而系統(tǒng)異炒窭可以處理也可以不處理,所以甸各,編譯器不強(qiáng)制用try..catch處理或用throws聲明垛贤,所以系統(tǒng)異常也稱為unchecked異常。
提示答題者:就按照三個級別去思考:虛擬機(jī)必須宕機(jī)的錯誤趣倾,程序可以死掉也可以不死掉的錯誤聘惦,程序不應(yīng)該死掉的錯誤;
44、請寫出你最常見到的5個runtime exception善绎。
這道題主要考你的代碼量到底多大黔漂,如果你長期寫代碼的,應(yīng)該經(jīng)常都看到過一些系統(tǒng)方面的異常禀酱,你不一定真要回答出5個具體的系統(tǒng)異常炬守,但你要能夠說出什么是系統(tǒng)異常,以及幾個系統(tǒng)異常就可以了剂跟,當(dāng)然减途,這些異常完全用其英文名稱來寫是最好的,如果實在寫不出曹洽,那就用中文吧鳍置,有總比沒有強(qiáng)!
所謂系統(tǒng)異常送淆,就是…..税产,它們都是RuntimeException的子類,在jdk doc中查RuntimeException類偷崩,就可以看到其所有的子類列表辟拷,也就是看到了所有的系統(tǒng)異常。我比較有印象的系統(tǒng)異常有:NullPointerException阐斜、ArrayIndexOutOfBoundsException衫冻、ClassCastException。
45智听、JAVA語言如何進(jìn)行異常處理羽杰,關(guān)鍵字:throws,throw,try,catch,finally分別代表什么意義?在try塊中可以拋出異常嗎到推?
46礼患、java中有幾種方法可以實現(xiàn)一個線程嘉裤?用什么關(guān)鍵字修飾同步方法? stop()和suspend()方法為何不推薦使用灯蝴?
java5以前柔袁,有如下兩種:
第一種:
new Thread(){}.start();這表示調(diào)用Thread子類對象的run方法,new Thread(){}表示一個Thread的匿名子類的實例對象捣卤,子類加上run方法后的代碼如下:
new Thread(){
public void run(){
}
}.start();
第二種:
new Thread(new Runnable(){}).start();這表示調(diào)用Thread對象接受的Runnable對象的run方法忍抽,new Runnable(){}表示一個Runnable的匿名子類的實例對象,runnable的子類加上run方法后的代碼如下:
new Thread(new Runnable(){
public voidrun(){
}
}
).start();
從java5開始,還有如下一些線程池創(chuàng)建多線程的方式:
ExecutorService pool = Executors.newFixedThreadPool(3)
for(int i=0;i<10;i++)
{
pool.execute(newRunable(){public void run(){}});
}
Executors.newCachedThreadPool().execute(new Runable(){publicvoid run(){}});
Executors.newSingleThreadExecutor().execute(new Runable(){publicvoid run(){}});
有兩種實現(xiàn)方法董朝,分別使用new Thread()和new Thread(runnable)形式鸠项,第一種直接調(diào)用thread的run方法,所以子姜,我們往往使用Thread子類祟绊,即new SubThread()。第二種調(diào)用runnable的run方法。
有兩種實現(xiàn)方法牧抽,分別是繼承Thread類與實現(xiàn)Runnable接口
用synchronized關(guān)鍵字修飾同步方法
反對使用stop()嘉熊,是因為它不安全。它會解除由線程獲取的所有鎖定扬舒,而且如果對象處于一種不連貫狀態(tài)阐肤,那么其他線程能在那種狀態(tài)下檢查和修改它們。結(jié)果很難檢查出真正的問題所在讲坎。suspend()方法容易發(fā)生死鎖孕惜。調(diào)用suspend()的時候,目標(biāo)線程會停下來衣赶,但卻仍然持有在這之前獲得的鎖定诊赊。此時厚满,其他任何線程都不能訪問鎖定的資源府瞄,除非被"掛起"的線程恢復(fù)運(yùn)行。對任何線程來說碘箍,如果它們想恢復(fù)目標(biāo)線程遵馆,同時又試圖使用任何一個鎖定的資源,就會造成死鎖丰榴。所以不應(yīng)該使用suspend()货邓,而應(yīng)在自己的Thread類中置入一個標(biāo)志,指出線程應(yīng)該活動還是掛起四濒。若標(biāo)志指出線程應(yīng)該掛起换况,便用wait()命其進(jìn)入等待狀態(tài)。若標(biāo)志指出線程應(yīng)當(dāng)恢復(fù)盗蟆,則用一個notify()重新啟動線程戈二。
47、sleep()和 wait()有什么區(qū)別?
(網(wǎng)上的答案:sleep是線程類(Thread)的方法喳资,導(dǎo)致此線程暫停執(zhí)行指定時間觉吭,給執(zhí)行機(jī)會給其他線程,但是監(jiān)控狀態(tài)依然保持仆邓,到時后會自動恢復(fù)鲜滩。調(diào)用sleep不會釋放對象鎖。 wait是Object類的方法节值,對此對象調(diào)用wait方法導(dǎo)致本線程放棄對象鎖徙硅,進(jìn)入等待此對象的等待鎖定池,只有針對此對象發(fā)出notify方法(或notifyAll)后本線程才進(jìn)入對象鎖定池準(zhǔn)備獲得對象鎖進(jìn)入運(yùn)行狀態(tài)搞疗。)
sleep就是正在執(zhí)行的線程主動讓出cpu嗓蘑,cpu去執(zhí)行其他線程,在sleep指定的時間過后,cpu才會回到這個線程上繼續(xù)往下執(zhí)行脐往,如果當(dāng)前線程進(jìn)入了同步鎖休吠,sleep方法并不會釋放鎖,即使當(dāng)前線程使用sleep方法讓出了cpu业簿,但其他被同步鎖擋住了的線程也無法得到執(zhí)行瘤礁。wait是指在一個已經(jīng)進(jìn)入了同步鎖的線程內(nèi),讓自己暫時讓出同步鎖梅尤,以便其他正在等待此鎖的線程可以得到同步鎖并運(yùn)行柜思,只有其他線程調(diào)用了notify方法(notify并不釋放鎖粟耻,只是告訴調(diào)用過wait方法的線程可以去參與獲得鎖的競爭了栅炒,但不是馬上得到鎖亏镰,因為鎖還在別人手里琴昆,別人還沒釋放大猛。如果notify方法后面的代碼還有很多痪蝇,需要這些代碼執(zhí)行完后才會釋放鎖急膀,可以在notfiy方法后增加一個等待和一些代碼峦阁,看看效果)钝腺,調(diào)用wait方法的線程就會解除wait狀態(tài)和程序可以再次得到鎖后繼續(xù)向下運(yùn)行抛姑。對于wait的講解一定要配合例子代碼來說明,才顯得自己真明白艳狐。
packagecom.huawei.interview;
publicclassMultiThread {
/**
*@paramargs
*/
public static voidmain(String[] args) {
//TODOAuto-generated method stub
newThread(newThread1()).start();
try{
Thread.sleep(10);
}catch(InterruptedException e) {
//TODOAuto-generated catchblock
e.printStackTrace();
}
newThread(newThread2()).start();
}
private static classThread1implementsRunnable
{
@Override
public voidrun() {
//TODOAuto-generated methodstub
//由于這里的Thread1和下面的Thread2內(nèi)部run方法要用同一對象作為監(jiān)視器定硝,我們這里不能用this,因為在Thread2里面的this和這個Thread1的this不是同一個對象毫目。我們用MultiThread.class這個字節(jié)碼對象蔬啡,當(dāng)前虛擬機(jī)里引用這個變量時,指向的都是同一個對象镀虐。
synchronized(MultiThread.class){
System.out.println("enterthread1...");
System.out.println("thread1is waiting");
try{
//釋放鎖有兩種方式箱蟆,第一種方式是程序自然離開監(jiān)視器的范圍,也就是離開了synchronized關(guān)鍵字管轄的代碼范圍粉私,另一種方式就是在synchronized關(guān)鍵字管轄的代碼內(nèi)部調(diào)用監(jiān)視器對象的wait方法顽腾。這里,使用wait方法釋放鎖诺核。
MultiThread.class.wait();
}catch(InterruptedException e) {
//TODOAuto-generatedcatch block
e.printStackTrace();
}
System.out.println("thread1is going on...");
System.out.println("thread1is being over!");
}
}
}
private static classThread2implementsRunnable
{
@Override
public voidrun() {
//TODOAuto-generated methodstub
synchronized(MultiThread.class){
System.out.println("enterthread2...");
System.out.println("thread2notify other thread can release wait status..");
//由于notify方法并不釋放鎖抄肖,即使thread2調(diào)用下面的sleep方法休息了10毫秒,但thread1仍然不會執(zhí)行窖杀,因為thread2沒有釋放鎖漓摩,所以Thread1無法得不到鎖。
MultiThread.class.notify();
System.out.println("thread2is sleeping ten millisecond...");
try{
Thread.sleep(10);
}catch(InterruptedExceptione) {
//TODOAuto-generatedcatch block
e.printStackTrace();
}
System.out.println("thread2is going on...");
System.out.println("thread2is being over!");
}
}
}
}
48入客、同步和異步有何異同管毙,在什么情況下分別使用他們腿椎?舉例說明。
如果數(shù)據(jù)將在線程間共享夭咬。例如正在寫的數(shù)據(jù)以后可能被另一個線程讀到啃炸,或者正在讀的數(shù)據(jù)可能已經(jīng)被另一個線程寫過了,那么這些數(shù)據(jù)就是共享數(shù)據(jù)卓舵,必須進(jìn)行同步存取南用。
當(dāng)應(yīng)用程序在對象上調(diào)用了一個需要花費很長時間來執(zhí)行的方法,并且不希望讓程序等待方法的返回時掏湾,就應(yīng)該使用異步編程裹虫,在很多情況下采用異步途徑往往更有效率。
49. 下面兩個方法同步嗎融击?(自己發(fā)明)
class Test
{
synchronizedstatic voidsayHello3()
{
}
synchronizedvoidgetX(){}
}
50筑公、多線程有幾種實現(xiàn)方法?同步有幾種實現(xiàn)方法?
多線程有兩種實現(xiàn)方法,分別是繼承Thread類與實現(xiàn)Runnable接口
同步的實現(xiàn)方面有兩種尊浪,分別是synchronized,wait與notify
wait():使一個線程處于等待狀態(tài)匣屡,并且釋放所持有的對象的lock。
sleep():使一個正在運(yùn)行的線程處于睡眠狀態(tài)际长,是一個靜態(tài)方法耸采,調(diào)用此方法要捕捉InterruptedException異常兴泥。
notify():喚醒一個處于等待狀態(tài)的線程工育,注意的是在調(diào)用此方法的時候,并不能確切的喚醒某一個等待狀態(tài)的線程搓彻,而是由JVM確定喚醒哪個線程如绸,而且不是按優(yōu)先級。
Allnotity():喚醒所有處入等待狀態(tài)的線程旭贬,注意并不是給所有喚醒線程一個對象的鎖怔接,而是讓它們競爭。
51稀轨、啟動一個線程是用run()還是start()? .
啟動一個線程是調(diào)用start()方法,使線程就緒狀態(tài),以后可以被調(diào)度為運(yùn)行狀態(tài)灸促,一個線程必須關(guān)聯(lián)一些具體的執(zhí)行代碼异旧,run()方法是該線程所關(guān)聯(lián)的執(zhí)行代碼。
52佣谐、當(dāng)一個線程進(jìn)入一個對象的一個synchronized方法后肚吏,其它線程是否可進(jìn)入此對象的其它方法?
分幾種情況:
1.其他方法前是否加了synchronized關(guān)鍵字,如果沒加狭魂,則能罚攀。
2.如果這個方法內(nèi)部調(diào)用了wait党觅,則可以進(jìn)入其他synchronized方法。
3.如果其他個方法都加了synchronized關(guān)鍵字斋泄,并且內(nèi)部沒有調(diào)用wait杯瞻,則不能。
4.如果其他方法是static炫掐,它用的同步鎖是當(dāng)前類的字節(jié)碼又兵,與非靜態(tài)的方法不能同步,因為非靜態(tài)的方法用的是this卒废。
53沛厨、線程的基本概念、線程的基本狀態(tài)以及狀態(tài)之間的關(guān)系
一個程序中可以有多條執(zhí)行線索同時執(zhí)行摔认,一個線程就是程序中的一條執(zhí)行線索逆皮,每個線程上都關(guān)聯(lián)有要執(zhí)行的代碼,即可以有多段程序代碼同時運(yùn)行参袱,每個程序至少都有一個線程电谣,即main方法執(zhí)行的那個線程。如果只是一個cpu抹蚀,它怎么能夠同時執(zhí)行多段程序呢剿牺?這是從宏觀上來看的,cpu一會執(zhí)行a線索环壤,一會執(zhí)行b線索晒来,切換時間很快,給人的感覺是a,b在同時執(zhí)行郑现,好比大家在同一個辦公室上網(wǎng)湃崩,只有一條鏈接到外部網(wǎng)線,其實接箫,這條網(wǎng)線一會為a傳數(shù)據(jù)攒读,一會為b傳數(shù)據(jù),由于切換時間很短暫辛友,所以薄扁,大家感覺都在同時上網(wǎng)。
狀態(tài):就緒废累,運(yùn)行邓梅,synchronize阻塞,wait和sleep掛起九默,結(jié)束震放。wait必須在synchronized內(nèi)部調(diào)用。
調(diào)用線程的start方法后線程進(jìn)入就緒狀態(tài)驼修,線程調(diào)度系統(tǒng)將就緒狀態(tài)的線程轉(zhuǎn)為運(yùn)行狀態(tài)殿遂,遇到synchronized語句時诈铛,由運(yù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)焕毫。
54、簡述synchronized和java.util.concurrent.locks.Lock的異同驶乾?
主要相同點:Lock能完成synchronized所實現(xiàn)的所有功能
主要不同點:Lock有比synchronized更精確的線程語義和更好的性能邑飒。synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放级乐,并且必須在finally從句中釋放疙咸。Lock還有更強(qiáng)大的功能铜涉,例如掩驱,它的tryLock方法可以非阻塞方式去拿鎖。
舉例說明(對下面的題用lock進(jìn)行了改寫):
packagecom.huawei.interview;
importjava.util.concurrent.locks.Lock;
importjava.util.concurrent.locks.ReentrantLock;
publicclassThreadTest {
/**
*@paramargs
*/
private intj;
privateLock lock =newReentrantLock();
public static voidmain(String[] args) {
//TODOAuto-generated method stub
ThreadTest tt =newThreadTest();
for(inti=0;i<2;i++)
{
newThread(tt.newAdder()).start();
newThread(tt.newSubtractor()).start();
}
}
private classSubtractorimplementsRunnable
{
@Override
public voidrun() {
//TODOAuto-generated methodstub
while(true)
{
/*synchronized (ThreadTest.this) {
System.out.println("j--="+ j--);
//這里拋異常了醇锚,鎖能釋放嗎贼穆?
}*/
lock.lock();
try
{
System.out.println("j--="+ j--);
}finally
{
lock.unlock();
}
}
}
}
private classAdderimplementsRunnable
{
@Override
public voidrun() {
//TODOAuto-generated methodstub
while(true)
{
/*synchronized (ThreadTest.this) {
System.out.println("j++="+ j++);
}*/
lock.lock();
try
{
System.out.println("j++="+ j++);
}finally
{
lock.unlock();
}
}
}
}
}
55题山、設(shè)計4個線程,其中兩個線程每次對j增加1故痊,另外兩個線程對j每次減少1顶瞳。寫出程序。
以下程序使用內(nèi)部類實現(xiàn)線程崖蜜,對j增減的時候沒有考慮順序問題浊仆。
public class ThreadTest1
{
private int j;
public static void main(String args[]){
ThreadTest1 tt=newThreadTest1();
Inc inc=tt.new Inc();
Dec dec=tt.new Dec();
for(inti=0;i<2;i++){
Thread t=newThread(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(inti=0;i<100;i++){
inc();
}
}
}
class Dec implements Runnable{
public void run(){
for(inti=0;i<100;i++){
dec();
}
}
}
}
----------隨手再寫的一個-------------
class A
{
JManger j =new JManager();
main()
{
new A().call();
}
void call
{
for(int i=0;i<2;i++)
{
new Thread(
newRunnable(){ public void run(){while(true){j.accumulate()}}}
).start();
new Thread(newRunnable(){ public void run(){while(true){j.sub()}}}).start();
}
}
}
class JManager
{
private j = 0;
public synchronized voidsubtract()
{
j--
}
public synchronized voidaccumulate()
{
j++;
}
}
56、子線程循環(huán)10次豫领,接著主線程循環(huán)100,接著又回到子線程循環(huán)10次舔琅,接著再回到主線程又循環(huán)100等恐,如此循環(huán)50次,請寫出程序备蚓。
最終的程序代碼如下:
publicclassThreadTest {
/**
*@paramargs
*/
public static voidmain(String[] args) {
//TODOAuto-generated method stub
newThreadTest().init();
}
public voidinit()
{
finalBusiness business =newBusiness();
newThread(
newRunnable()
{
public voidrun() {
for(inti=0;i<50;i++)
{
business.SubThread(i);
}
}
}
).start();
for(inti=0;i<50;i++)
{
business.MainThread(i);
}
}
private classBusiness
{
booleanbShouldSub =true;//這里相當(dāng)于定義了控制該誰執(zhí)行的一個信號燈
public synchronized voidMainThread(inti)
{
if(bShouldSub)
try{
this.wait();
}catch(InterruptedException e) {
//TODOAuto-generatedcatch block
e.printStackTrace();
}
for(intj=0;j<5;j++)
{
System.out.println(Thread.currentThread().getName()+ ":i=" + i +",j=" + j);
}
bShouldSub =true;
this.notify();
}
public synchronized voidSubThread(inti)
{
if(!bShouldSub)
try{
this.wait();
}catch(InterruptedExceptione) {
//TODOAuto-generatedcatch block
e.printStackTrace();
}
for(intj=0;j<10;j++)
{
System.out.println(Thread.currentThread().getName()+ ":i=" + i +",j=" + j);
}
bShouldSub =false;
this.notify();
}
}
}
備注:不可能一上來就寫出上面的完整代碼课蔬,最初寫出來的代碼如下,問題在于兩個線程的代碼要參照同一個變量郊尝,即這兩個線程的代碼要共享數(shù)據(jù)二跋,所以,把這兩個線程的執(zhí)行代碼搬到同一個類中去:
packagecom.huawei.interview.lym;
publicclassThreadTest {
private static booleanbShouldMain=false;
public static voidmain(String[]args) {
//TODOAuto-generated method stub
/*new Thread(){
public void run()
{
for(int i=0;i<50;i++)
{
for(int j=0;j<10;j++)
{
System.out.println("i="+ i + ",j=" + j);
}
}
}
}.start();*/
//final String str = newString("");
newThread(
newRunnable()
{
public voidrun()
{
for(inti=0;i<50;i++)
{
synchronized(ThreadTest.class) {
if(bShouldMain)
{
try{
ThreadTest.class.wait();}
catch(InterruptedException e) {
e.printStackTrace();
}
}
for(intj=0;j<10;j++)
{
System.out.println(
Thread.currentThread().getName()+
"i="+ i + ",j=" + j);
}
bShouldMain=true;
ThreadTest.class.notify();
}
}
}
}
).start();
for(inti=0;i<50;i++)
{
synchronized(ThreadTest.class){
if(!bShouldMain)
{
try{
ThreadTest.class.wait();}
catch(InterruptedException e) {
e.printStackTrace();
}
}
for(intj=0;j<5;j++)
{
System.out.println(
Thread.currentThread().getName()+
"i=" + i +",j=" + j);
}
bShouldMain=false;
ThreadTest.class.notify();
}
}
}
}
下面使用jdk5中的并發(fā)庫來實現(xiàn)的:
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
public class ThreadTest
{
private static Locklock = new ReentrantLock();
private staticCondition subThreadCondition = lock.newCondition();
private staticboolean bBhouldSubThread = false;
public static voidmain(String [] args)
{
ExecutorServicethreadPool = Executors.newFixedThreadPool(3);
threadPool.execute(newRunnable(){
publicvoid run()
{
for(inti=0;i<50;i++)
{
lock.lock();
try
{
if(!bBhouldSubThread)
subThreadCondition.await();
for(intj=0;j<10;j++)
{
System.out.println(Thread.currentThread().getName()+ ",j=" + j);
}
bBhouldSubThread= false;
subThreadCondition.signal();
}catch(Exceptione)
{
}
finally
{
lock.unlock();
}
}
}
});
threadPool.shutdown();
for(inti=0;i<50;i++)
{
lock.lock();
try
{
if(bBhouldSubThread)
subThreadCondition.await();
for(intj=0;j<10;j++)
{
System.out.println(Thread.currentThread().getName()+ ",j=" + j);
}
bBhouldSubThread= true;
subThreadCondition.signal();
}catch(Exceptione)
{
}
finally
{
lock.unlock();
}
}
}
}
57流昏、介紹Collection框架的結(jié)構(gòu)
答:隨意發(fā)揮題扎即,天南海北誰便談吞获,只要讓別覺得你知識淵博,理解透徹即可谚鄙。
58各拷、Collection框架中實現(xiàn)比較要實現(xiàn)什么接口
comparable/comparator
59、ArrayList和Vector的區(qū)別
答:
這兩個類都實現(xiàn)了List接口(List接口繼承了Collection接口)闷营,他們都是有序集合烤黍,即存儲在這兩個集合中的元素的位置都是有順序的,相當(dāng)于一種動態(tài)的數(shù)組傻盟,我們以后可以按位置索引號取出某個元素速蕊,,并且其中的數(shù)據(jù)是允許重復(fù)的娘赴,這是HashSet之類的集合的最大不同處互例,HashSet之類的集合不可以按索引號去檢索其中的元素,也不允許有重復(fù)的元素(本來題目問的與hashset沒有任何關(guān)系筝闹,但為了說清楚ArrayList與Vector的功能媳叨,我們使用對比方式,更有利于說明問題)关顷。
接著才說ArrayList與Vector的區(qū)別糊秆,這主要包括兩個方面:.
(1)同步性:
Vector是線程安全的,也就是說是它的方法之間是線程同步的议双,而ArrayList是線程序不安全的痘番,它的方法之間是線程不同步的。如果只有一個線程會訪問到集合平痰,那最好是使用ArrayList汞舱,因為它不考慮線程安全,效率會高些宗雇;如果有多個線程會訪問到集合昂芜,那最好是使用Vector,因為不需要我們自己再去考慮和編寫線程安全的代碼赔蒲。
備注:對于Vector&ArrayList泌神、Hashtable&HashMap,要記住線程安全的問題舞虱,記住Vector與Hashtable是舊的欢际,是java一誕生就提供了的,它們是線程安全的矾兜,ArrayList與HashMap是java2時才提供的损趋,它們是線程不安全的飞几。所以薯定,我們講課時先講老的。
(2)數(shù)據(jù)增長:
ArrayList與Vector都有一個初始的容量大小,當(dāng)存儲進(jìn)它們里面的元素的個數(shù)超過了容量時槐秧,就需要增加ArrayList與Vector的存儲空間贤壁,每次要增加存儲空間時疏遏,不是只增加一個存儲單元提揍,而是增加多個存儲單元,每次增加的存儲單元的個數(shù)在內(nèi)存空間利用與程序效率之間要取得一定的平衡畸冲。Vector默認(rèn)增長為原來兩倍嫉髓,而ArrayList的增長策略在文檔中沒有明確規(guī)定(從源代碼看到的是增長為原來的1.5倍)。ArrayList與Vector都可以設(shè)置初始的空間大小邑闲,Vector還可以設(shè)置增長的空間大小算行,而ArrayList沒有提供設(shè)置增長空間的方法。
總結(jié):即Vector增長原來的一倍苫耸,ArrayList增加原來的0.5倍州邢。
60、HashMap和Hashtable的區(qū)別
(條理上還需要整理褪子,也是先說相同點量淌,再說不同點)
HashMap是Hashtable的輕量級實現(xiàn)(非線程安全的實現(xiàn)),他們都完成了Map接口嫌褪,主要區(qū)別在于HashMap允許空(null)鍵值(key),由于非線程安全呀枢,在只有一個線程訪問的情況下,效率要高于Hashtable笼痛。
HashMap允許將null作為一個entry的key或者value裙秋,而Hashtable不允許。
HashMap把Hashtable的contains方法去掉了缨伊,改成containsvalue和containsKey摘刑。因為contains方法容易讓人引起誤解。
Hashtable繼承自Dictionary類刻坊,而HashMap是Java1.2引進(jìn)的Map interface的一個實現(xiàn)枷恕。
最大的不同是,Hashtable的方法是Synchronize的紧唱,而HashMap不是活尊,在多個線程訪問Hashtable時,不需要自己為它的方法實現(xiàn)同步漏益,而HashMap就必須為之提供外同步。
Hashtable和HashMap采用的hash/rehash算法都大概一樣深胳,所以性能不會有很大的差異绰疤。
就HashMap與HashTable主要從三方面來說。
一.歷史原因:Hashtable是基于陳舊的Dictionary類的舞终,HashMap是Java 1.2引進(jìn)的Map接口的一個實現(xiàn)
二.同步性:Hashtable是線程安全的轻庆,也就是說是同步的癣猾,而HashMap是線程序不安全的,不是同步的
三.值:只有HashMap可以讓你將空值作為一個表的條目的key或value
61余爆、List和 Map區(qū)別?
一個是存儲單列數(shù)據(jù)的集合纷宇,另一個是存儲鍵和值這樣的雙列數(shù)據(jù)的集合,List中存儲的數(shù)據(jù)是有順序蛾方,并且允許重復(fù)像捶;Map中存儲的數(shù)據(jù)是沒有順序的,其鍵是不能重復(fù)的桩砰,它的值是可以有重復(fù)的拓春。
62、List, Set, Map是否繼承自Collection接口?
List亚隅,Set是硼莽,Map不是
63、List煮纵、Map懂鸵、Set三個接口,存取元素時行疏,各有什么特點匆光?
這樣的題屬于隨意發(fā)揮題:這樣的題比較考水平,兩個方面的水平:一是要真正明白這些內(nèi)容隘擎,二是要有較強(qiáng)的總結(jié)和表述能力械念。如果你明白,但表述不清楚裁僧,在別人那里則等同于不明白贴届。
首先,List與Set具有相似性震桶,它們都是單列元素的集合休傍,所以,它們有一個功共同的父接口蹲姐,叫Collection磨取。Set里面不允許有重復(fù)的元素,所謂重復(fù)柴墩,即不能有兩個相等(注意忙厌,不是僅僅是相同)的對象,即假設(shè)Set集合中有了一個A對象江咳,現(xiàn)在我要向Set集合再存入一個B對象逢净,但B對象與A對象equals相等,則B對象存儲不進(jìn)去,所以爹土,Set集合的add方法有一個boolean的返回值甥雕,當(dāng)集合中沒有某個元素,此時add方法可成功加入該元素時胀茵,則返回true社露,當(dāng)集合含有與某個元素equals相等的元素時,此時add方法無法加入該元素琼娘,返回結(jié)果為false峭弟。Set取元素時,沒法說取第幾個轨奄,只能以Iterator接口取得所有的元素孟害,再逐一遍歷各個元素。
List表示有先后順序的集合挪拟,注意挨务,不是那種按年齡、按大小玉组、按價格之類的排序谎柄。當(dāng)我們多次調(diào)用add(Obj e)方法時,每次加入的對象就像火車站買票有排隊順序一樣惯雳,按先來后到的順序排序朝巫。有時候,也可以插隊石景,即調(diào)用add(int index,Obj e)方法劈猿,就可以指定當(dāng)前對象在集合中的存放位置。一個對象可以被反復(fù)存儲進(jìn)List中潮孽,每調(diào)用一次add方法揪荣,這個對象就被插入進(jìn)集合中一次,其實往史,并不是把這個對象本身存儲進(jìn)了集合中仗颈,而是在集合中用一個索引變量指向這個對象,當(dāng)這個對象被add多次時椎例,即相當(dāng)于集合中有多個索引指向了這個對象挨决,如圖x所示。List除了可以以Iterator接口取得所有的元素订歪,再逐一遍歷各個元素之外脖祈,還可以調(diào)用get(index i)來明確說明取第幾個。
Map與List和Set不同刷晋,它是雙列的集合撒犀,其中有put方法福压,定義如下:put(obj key,objvalue)掏秩,每次存儲時或舞,要存儲一對key/value,不能存儲重復(fù)的key蒙幻,這個重復(fù)的規(guī)則也是按equals比較相等映凳。取則可以根據(jù)key獲得相應(yīng)的value,即get(Object key)返回值為key所對應(yīng)的value邮破。另外,也可以獲得所有的key的結(jié)合,還可以獲得所有的value的結(jié)合础米,還可以獲得key和value組合成的Map.Entry對象的集合汗菜。
List 以特定次序來持有元素,可有重復(fù)元素摧莽。Set無法擁有重復(fù)元素,內(nèi)部排序庙洼。Map保存key-value值,value可多值镊辕。
HashSet按照hashcode值的某種運(yùn)算方式進(jìn)行存儲油够,而不是直接按hashCode值的大小進(jìn)行存儲。例如征懈,"abc"---> 78石咬,"def" ---> 62,"xyz" ---> 65在hashSet中的存儲順序不是62,65,78卖哎,這些問題感謝以前一個叫崔健的學(xué)員提出鬼悠,最后通過查看源代碼給他解釋清楚,看本次培訓(xùn)學(xué)員當(dāng)中有多少能看懂源碼亏娜。LinkedHashSet按插入的順序存儲焕窝,那被存儲對象的hashcode方法還有什么作用呢?學(xué)員想想!hashset集合比較兩個對象是否相等照藻,首先看hashcode方法是否相等袜啃,然后看equals方法是否相等。new兩個Student插入到HashSet中幸缕,看HashSet的size群发,實現(xiàn)hashcode和equals方法后再看size。
同一個對象可以在Vector中加入多次发乔。往集合里面加元素熟妓,相當(dāng)于集合里用一根繩子連接到了目標(biāo)對象。往HashSet中卻加不了多次的栏尚。
64起愈、說出ArrayList,Vector, LinkedList的存儲性能和特性
ArrayList和Vector都是使用數(shù)組方式存儲數(shù)據(jù),此數(shù)組元素數(shù)大于實際存儲的數(shù)據(jù)以便增加和插入元素,它們都允許直接按序號索引元素抬虽,但是插入元素要涉及數(shù)組元素移動等內(nèi)存操作官觅,所以索引數(shù)據(jù)快而插入數(shù)據(jù)慢,Vector由于使用了synchronized方法(線程安全)阐污,通常性能上較ArrayList差休涤,而LinkedList使用雙向鏈表實現(xiàn)存儲,按序號索引數(shù)據(jù)需要進(jìn)行前向或后向遍歷笛辟,但是插入數(shù)據(jù)時只需要記錄本項的前后項即可功氨,所以插入速度較快。
LinkedList也是線程不安全的手幢,LinkedList提供了一些方法捷凄,使得LinkedList可以被當(dāng)作堆棧和隊列來使用。
65围来、去掉一個Vector集合中重復(fù)的元素
Vector newVector = new Vector();
For (int i=0;i
{
Object obj = vector.get(i);
if(!newVector.contains(obj);
newVector.add(obj);
}
還有一種簡單的方式跺涤,HashSet set = new HashSet(vector);
66、Collection和 Collections的區(qū)別管钳。
Collection是集合類的上級接口钦铁,繼承與他的接口主要有Set和List.
Collections是針對集合類的一個幫助類,他提供一系列靜態(tài)方法實現(xiàn)對各種集合的搜索才漆、排序牛曹、線程安全化等操作。
67醇滥、Set里的元素是不能重復(fù)的黎比,那么用什么方法來區(qū)分重復(fù)與否呢?是用==還是equals()?它們有何區(qū)別?
Set里的元素是不能重復(fù)的,元素重復(fù)與否是使用equals()方法進(jìn)行判斷的鸳玩。
equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋阅虫,為的是當(dāng)兩個分離的對象的內(nèi)容和類型相配的話,返回真值不跟。
68颓帝、你所知道的集合類都有哪些?主要方法窝革?
最常用的集合類是 List 和 Map购城。 List的具體實現(xiàn)包括 ArrayList和 Vector,它們是可變大小的列表,比較適合構(gòu)建、存儲和操作任何類型對象的元素列表玫芦。 List適用于按數(shù)值索引訪問元素的情形。
Map 提供了一個更通用的元素存儲方法稿黄。 Map集合類用于存儲元素對(稱作"鍵"和"值")未巫,其中每個鍵映射到一個值唇撬。
ArrayList/VectoràList
àCollection
HashSet/TreeSetàSet
PropetiesàHashTable
àMap
Treemap/HashMap
我記的不是方法名拴鸵,而是思想兰英,我知道它們都有增刪改查的方法撇叁,但這些方法的具體名稱,我記得不是很清楚箭昵,對于set税朴,大概的方法是add,remove, contains;對于map家制,大概的方法就是put,remove,contains等泡一,因為颤殴,我只要在eclispe下按點操作符,很自然的這些方法就出來了鼻忠。我記住的一些思想就是List類會有g(shù)et(int index)這樣的方法涵但,因為它可以按順序取元素,而set類中沒有g(shù)et(int index)這樣的方法帖蔓。List和set都可以迭代出所有元素矮瘟,迭代時先要得到一個iterator對象,所以塑娇,set和list類都有一個iterator方法澈侠,用于返回那個iterator對象。map可以返回三個集合埋酬,一個是返回所有的key的集合哨啃,另外一個返回的是所有value的集合,再一個返回的key和value組合成的EntrySet對象的集合写妥,map也有g(shù)et方法拳球,參數(shù)是key,返回值是key對應(yīng)的value珍特。
69祝峻、兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code扎筒,這句話對不對?
對莱找。
如果對象要保存在HashSet或HashMap中,它們的equals相等砸琅,那么宋距,它們的hashcode值就必須相等。
如果不是要保存在HashSet或HashMap症脂,則與hashcode沒有什么關(guān)系了谚赎,這時候hashcode不等是可以的淫僻,例如arrayList存儲的對象就不用實現(xiàn)hashcode,當(dāng)然壶唤,我們沒有理由不實現(xiàn)雳灵,通常都會去實現(xiàn)的。
70闸盔、TreeSet里面放對象悯辙,如果同時放入了父類和子類的實例對象,那比較時使用的是父類的compareTo方法迎吵,還是使用的子類的compareTo方法躲撰,還是拋異常!
(應(yīng)該是沒有針對問題的確切的答案击费,當(dāng)前的add方法放入的是哪個對象拢蛋,就調(diào)用哪個對象的compareTo方法,至于這個compareTo方法怎么做蔫巩,就看當(dāng)前這個對象的類中是如何編寫這個方法的)
實驗代碼:
publicclassParentimplementsComparable {
private intage = 0;
publicParent(intage){
this.age = age;
}
public intcompareTo(Object o){
//TODOAuto-generated method stub
System.out.println("method ofparent");
Parent o1 = (Parent)o;
returnage>o1.age?1:age
}
}
publicclassChildextendsParent {
publicChild(){
super(3);
}
public intcompareTo(Object o){
//TODOAuto-generated methodstub
System.out.println("methodof child");
//Child o1 = (Child)o;
return1;
}
}
publicclassTreeSetTest {
/**
*@paramargs
*/
public static voidmain(String[] args) {
//TODOAuto-generated method stub
TreeSet set =newTreeSet();
set.add(newParent(3));
set.add(newChild());
set.add(newParent(4));
System.out.println(set.size());
}
}
71谆棱、說出一些常用的類,包圆仔,接口垃瞧,請各舉5個
要讓人家感覺你對java ee開發(fā)很熟,所以坪郭,不能僅僅只列core java中的那些東西壕曼,要多列你在做ssh項目中涉及的那些東西单雾。就寫你最近寫的那些程序中涉及的那些類懊缺。
常用的類:BufferedReaderBufferedWriter ?FileReader FileWirter ?String ?Integer
java.util.Date达吞,System,Class绸罗,List,HashMap
常用的包:java.langjava.io java.util ?java.sql,javax.servlet,org.apache.strtuts.action,org.hibernate
常用的接口:RemoteList Map ?Document ?NodeList,Servlet,HttpServletRequest,HttpServletResponse,Transaction(Hibernate)意推、Session(Hibernate),HttpSession
72、java中有幾種類型的流珊蟀?JDK為每種類型的流提供了一些抽象類以供繼承菊值,請說出他們分別是哪些類?
字節(jié)流育灸,字符流腻窒。字節(jié)流繼承于InputStream OutputStream,字符流繼承于InputStreamReaderOutputStreamWriter磅崭。在java.io包中還有許多其他的流儿子,主要是為了提高性能和使用方便。
73砸喻、字節(jié)流與字符流的區(qū)別
要把一片二進(jìn)制數(shù)據(jù)數(shù)據(jù)逐一輸出到某個設(shè)備中柔逼,或者從某個設(shè)備中逐一讀取一片二進(jìn)制數(shù)據(jù)蒋譬,不管輸入輸出設(shè)備是什么,我們要用統(tǒng)一的方式來完成這些操作愉适,用一種抽象的方式進(jìn)行描述犯助,這個抽象描述方式起名為IO流,對應(yīng)的抽象類為OutputStream和InputStream维咸,不同的實現(xiàn)類就代表不同的輸入和輸出設(shè)備剂买,它們都是針對字節(jié)進(jìn)行操作的。
在應(yīng)用中癌蓖,經(jīng)常要完全是字符的一段文本輸出去或讀進(jìn)來瞬哼,用字節(jié)流可以嗎?計算機(jī)中的一切最終都是二進(jìn)制的字節(jié)形式存在费坊。對于“中國”這些字符倒槐,首先要得到其對應(yīng)的字節(jié),然后將字節(jié)寫入到輸出流附井。讀取時,首先讀到的是字節(jié)两残,可是我們要把它顯示為字符永毅,我們需要將字節(jié)轉(zhuǎn)換成字符。由于這樣的需求很廣泛人弓,人家專門提供了字符流的包裝類沼死。
底層設(shè)備永遠(yuǎn)只接受字節(jié)數(shù)據(jù),有時候要寫字符串到底層設(shè)備崔赌,需要將字符串轉(zhuǎn)成字節(jié)再進(jìn)行寫入意蛀。字符流是字節(jié)流的包裝,字符流則是直接接受字符串健芭,它內(nèi)部將串轉(zhuǎn)成字節(jié)县钥,再寫入底層設(shè)備,這為我們向IO設(shè)別寫入或讀取字符串提供了一點點方便慈迈。
字符向字節(jié)轉(zhuǎn)換時若贮,要注意編碼的問題,因為字符串轉(zhuǎn)成字節(jié)數(shù)組痒留,
其實是轉(zhuǎn)成該字符的某種編碼的字節(jié)形式谴麦,讀取也是反之的道理。
講解字節(jié)流與字符流關(guān)系的代碼案例:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class IOTest {
public static void main(String[]args) throws Exception {
String str = "中國人";
/*FileOutputStreamfos ?= newFileOutputStream("1.txt");
fos.write(str.getBytes("UTF-8"));
fos.close();*/
/*FileWriter fw =new FileWriter("1.txt");
fw.write(str);
fw.close();*/
PrintWriter pw =new PrintWriter("1.txt","utf-8");
pw.write(str);
pw.close();
/*FileReader fr =new FileReader("1.txt");
char[] buf = newchar[1024];
int len =fr.read(buf);
String myStr = newString(buf,0,len);
System.out.println(myStr);*/
/*FileInputStreamfr = new FileInputStream("1.txt");
byte[] buf = newbyte[1024];
int len =fr.read(buf);
String myStr = newString(buf,0,len,"UTF-8");
System.out.println(myStr);*/
BufferedReader br =new BufferedReader(
newInputStreamReader(
newFileInputStream("1.txt"),"UTF-8"
)
);
String myStr =br.readLine();
br.close();
System.out.println(myStr);
}
}
74伸头、什么是java序列化匾效,如何實現(xiàn)java序列化?或者請解釋Serializable接口的作用恤磷。
我們有時候?qū)⒁粋€java對象變成字節(jié)流的形式傳出去或者從一個字節(jié)流中恢復(fù)成一個java對象面哼,例如野宜,要將java對象存儲到硬盤或者傳送給網(wǎng)絡(luò)上的其他計算機(jī),這個過程我們可以自己寫代碼去把一個java對象變成某個格式的字節(jié)流再傳輸精绎,但是速缨,jre本身就提供了這種支持,我們可以調(diào)用OutputStream的writeObject方法來做代乃,如果要讓java幫我們做旬牲,要被傳輸?shù)膶ο蟊仨殞崿F(xiàn)serializable接口修赞,這樣匆背,javac編譯時就會進(jìn)行特殊處理漓踢,編譯的類才可以被writeObject方法操作掀鹅,這就是所謂的序列化党巾。需要被序列化的類必須實現(xiàn)Serializable接口卓研,該接口是一個mini接口早敬,其中沒有需要實現(xiàn)的方法寞埠,implementsSerializable只是為了標(biāo)注該對象是可被序列化的摩骨。
例如通贞,在web開發(fā)中,如果對象被保存在了Session中恼五,tomcat在重啟時要把Session對象序列化到硬盤昌罩,這個對象就必須實現(xiàn)Serializable接口。如果對象要經(jīng)過分布式系統(tǒng)進(jìn)行網(wǎng)絡(luò)傳輸或通過rmi等遠(yuǎn)程調(diào)用灾馒,這就需要在網(wǎng)絡(luò)上傳輸對象茎用,被傳輸?shù)膶ο缶捅仨殞崿F(xiàn)Serializable接口。
75睬罗、描述一下JVM加載class文件的原理機(jī)制?
JVM中類的裝載是由ClassLoader和它的子類來實現(xiàn)的,Java ClassLoader是一個重要的Java運(yùn)行時系統(tǒng)組件轨功。它負(fù)責(zé)在運(yùn)行時查找和裝入類文件的類。
76容达、heap和stack有什么區(qū)別古涧。
java的內(nèi)存分為兩類,一類是棧內(nèi)存董饰,一類是堆內(nèi)存蒿褂。棧內(nèi)存是指程序進(jìn)入一個方法時,會為這個方法單獨分配一塊私屬存儲空間卒暂,用于存儲這個方法內(nèi)部的局部變量啄栓,當(dāng)這個方法結(jié)束時,分配給這個方法的棧會釋放也祠,這個棧中的變量也將隨之釋放昙楚。
堆是與棧作用不同的內(nèi)存,一般用于存放不放在當(dāng)前方法棧中的那些數(shù)據(jù)诈嘿,例如堪旧,使用new創(chuàng)建的對象都放在堆里削葱,所以,它不會隨方法的結(jié)束而消失淳梦。方法中的局部變量使用final修飾后析砸,放在堆中,而不是棧中爆袍。
77首繁、GC是什么?為什么要有GC?
GC是垃圾收集的意思(Gabage Collection),內(nèi)存處理是編程人員容易出現(xiàn)問題的地方,忘記或者錯誤的內(nèi)存回收會導(dǎo)致程序或系統(tǒng)的不穩(wěn)定甚至崩潰陨囊,Java提供的GC功能可以自動監(jiān)測對象是否超過作用域從而達(dá)到自動回收內(nèi)存的目的弦疮,Java語言沒有提供釋放已分配內(nèi)存的顯示操作方法。
78蜘醋、垃圾回收的優(yōu)點和原理胁塞。并考慮2種回收機(jī)制。
Java語言中一個顯著的特點就是引入了垃圾回收機(jī)制压语,使c++程序員最頭疼的內(nèi)存管理的問題迎刃而解啸罢,它使得Java程序員在編寫程序的時候不再需要考慮內(nèi)存管理。由于有個垃圾回收機(jī)制胎食,Java中的對象不再有"作用域"的概念伺糠,只有對象的引用才有"作用域"。垃圾回收可以有效的防止內(nèi)存泄露斥季,有效的使用可以使用的內(nèi)存。垃圾回收器通常是作為一個單獨的低級別的線程運(yùn)行累驮,不可預(yù)知的情況下對內(nèi)存堆中已經(jīng)死亡的或者長時間沒有使用的對象進(jìn)行清楚和回收酣倾,程序員不能實時的調(diào)用垃圾回收器對某個對象或所有對象進(jìn)行垃圾回收“ǎ回收機(jī)制有分代復(fù)制垃圾回收和標(biāo)記垃圾回收躁锡,增量垃圾回收。
79置侍、垃圾回收器的基本原理是什么映之?垃圾回收器可以馬上回收內(nèi)存嗎?有什么辦法主動通知虛擬機(jī)進(jìn)行垃圾回收丧鸯?
對于GC來說葛闷,當(dāng)程序員創(chuàng)建對象時惠勒,GC就開始監(jiān)控這個對象的地址、大小以及使用情況蠢甲。通常,GC采用有向圖的方式記錄和管理堆(heap)中的所有對象据忘。通過這種方式確定哪些對象是"可達(dá)的"鹦牛,哪些對象是"不可達(dá)的"搞糕。當(dāng)GC確定一些對象為"不可達(dá)"時,GC就有責(zé)任回收這些內(nèi)存空間曼追∏涎觯可以。程序員可以手動執(zhí)行System.gc()礼殊,通知GC運(yùn)行驹吮,但是Java語言規(guī)范并不保證GC一定會執(zhí)行。
80膏燕、什么時候用assert钥屈。
assertion(斷言)在軟件開發(fā)中是一種常用的調(diào)試方式,很多開發(fā)語言中都支持這種機(jī)制坝辫。在實現(xiàn)中篷就,assertion就是在程序中的一條語句,它對一個boolean表達(dá)式進(jìn)行檢查近忙,一個正確程序必須保證這個boolean表達(dá)式的值為true竭业;如果該值為false,說明程序已經(jīng)處于不正確的狀態(tài)下及舍,assert將給出警告或退出未辆。一般來說,assertion用于保證程序最基本锯玛、關(guān)鍵的正確性咐柜。assertion檢查通常在開發(fā)和測試時開啟。為了提高性能攘残,在軟件發(fā)布后拙友,assertion檢查通常是關(guān)閉的。
packagecom.huawei.interview;
publicclassAssertTest {
/**
*@paramargs
*/
public static voidmain(String[] args) {
//TODOAuto-generated method stub
inti = 0;
for(i=0;i<5;i++)
{
System.out.println(i);
}
//假設(shè)程序不小心多了一句--i;
--i;
asserti==5;
}
}
81歼郭、java中會存在內(nèi)存泄漏嗎遗契,請簡單描述。
所謂內(nèi)存泄露就是指一個不再被程序使用的對象或變量一直被占據(jù)在內(nèi)存中病曾。java中有垃圾回收機(jī)制牍蜂,它可以保證一對象不再被引用的時候,即對象編程了孤兒的時候泰涂,對象將自動被垃圾回收器從內(nèi)存中清除掉鲫竞。由于Java使用有向圖的方式進(jìn)行垃圾回收管理,可以消除引用循環(huán)的問題负敏,例如有兩個對象贡茅,相互引用,只要它們和根進(jìn)程不可達(dá)的,那么GC也是可以回收它們的顶考,例如下面的代碼可以看到這種情況的內(nèi)存回收:
packagecom.huawei.interview;
importjava.io.IOException;
publicclassGarbageTest {
/**
*@paramargs
*@throwsIOException
*/
public static voidmain(String[] args)throwsIOException {
//TODOAuto-generated method stub
try{
gcTest();
}catch(IOException e) {
//TODOAuto-generated catch block
e.printStackTrace();
}
System.out.println("hasexited gcTest!");
System.in.read();
System.in.read();
System.out.println("out begingc!");
for(inti=0;i<100;i++)
{
System.gc();
System.in.read();
System.in.read();
}
}
private static voidgcTest()throwsIOException {
System.in.read();
System.in.read();
Person p1 =newPerson();
System.in.read();
System.in.read();
Person p2 =newPerson();
p1.setMate(p2);
p2.setMate(p1);
System.out.println("beforeexit gctest!");
System.in.read();
System.in.read();
System.gc();
System.out.println("exitgctest!");
}
private static classPerson
{
byte[] data =new byte[20000000];
Person mate =null;
public voidsetMate(Personother)
{
mate = other;
}
}
}
java中的內(nèi)存泄露的情況:長生命周期的對象持有短生命周期對象的引用就很可能發(fā)生內(nèi)存泄露赁还,盡管短生命周期對象已經(jīng)不再需要,但是因為長生命周期對象持有它的引用而導(dǎo)致不能被回收驹沿,這就是java中內(nèi)存泄露的發(fā)生場景艘策,通俗地說,就是程序員可能創(chuàng)建了一個對象渊季,以后一直不再使用這個對象朋蔫,這個對象卻一直被引用,即這個對象無用但是卻無法被垃圾回收器回收的却汉,這就是java中可能出現(xiàn)內(nèi)存泄露的情況驯妄,例如,緩存系統(tǒng)合砂,我們加載了一個對象放在緩存中(例如放在一個全局map對象中)青扔,然后一直不再使用它,這個對象一直被緩存引用翩伪,但卻不再被使用微猖。
檢查java中的內(nèi)存泄露,一定要讓程序?qū)⒏鞣N分支情況都完整執(zhí)行到程序結(jié)束缘屹,然后看某個對象是否被使用過凛剥,如果沒有导帝,則才能判定這個對象屬于內(nèi)存泄露客们。
如果一個外部類的實例對象的方法返回了一個內(nèi)部類的實例對象,這個內(nèi)部類對象被長期引用了丝蹭,即使那個外部類實例對象不再被使用互亮,但由于內(nèi)部類持久外部類的實例對象盲憎,這個外部類對象將不會被垃圾回收,這也會造成內(nèi)存泄露胳挎。
下面內(nèi)容來自于網(wǎng)上(主要特點就是清空堆棧中的某個元素,并不是徹底把它從數(shù)組中拿掉溺森,而是把存儲的總數(shù)減少慕爬,本人寫得可以比這個好,在拿掉某個元素時屏积,順便也讓它從數(shù)組中消失医窿,將那個元素所在的位置的值設(shè)置為null即可):
我實在想不到比那個堆棧更經(jīng)典的例子了,以致于我還要引用別人的例子,下面的例子不是我想到的炊林,是書上看到的姥卢,當(dāng)然如果沒有在書上看到,可能過一段時間我自己也想的到,可是那時我說是我自己想到的也沒有人相信的独榴。
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)該很簡單僧叉,假如堆棧加了10個元素,然后全部彈出來棺榔,雖然堆棧是空的瓶堕,沒有我們要的東西,但是這是個對象是無法回收的症歇,這個才符合了內(nèi)存泄露的兩個條件:無用郎笆,無法回收。
但是就是存在這樣的東西也不一定會導(dǎo)致什么樣的后果忘晤,如果這個堆棧用的比較少宛蚓,也就浪費了幾個K內(nèi)存而已,反正我們的內(nèi)存都上G了设塔,哪里會有什么影響凄吏,再說這個東西很快就會被回收的,有什么關(guān)系壹置。下面看兩個例子竞思。
例子1
public class Bad{
public static Stack s=Stack();
static{
s.push(new Object());
s.pop(); //這里有一個對象發(fā)生內(nèi)存泄露
s.push(new Object()); //上面的對象可以被回收了,等于是自愈了
}
}
因為是static钞护,就一直存在到程序退出盖喷,但是我們也可以看到它有自愈功能,就是說如果你的Stack最多有100個對象难咕,那么最多也就只有100個對象無法被回收其實這個應(yīng)該很容易理解课梳,Stack內(nèi)部持有100個引用,最壞的情況就是他們都是無用的余佃,因為我們一旦放新的進(jìn)取暮刃,以前的引用自然消失!
內(nèi)存泄露的另外一種情況:當(dāng)一個對象被存儲進(jìn)HashSet集合中以后爆土,就不能修改這個對象中的那些參與計算哈希值的字段了椭懊,否則,對象修改后的哈希值與最初存儲進(jìn)HashSet集合中時的哈希值就不同了步势,在這種情況下氧猬,即使在contains方法使用該對象的當(dāng)前引用作為的參數(shù)去HashSet集合中檢索對象,也將返回找不到對象的結(jié)果坏瘩,這也會導(dǎo)致無法從HashSet集合中單獨刪除當(dāng)前對象盅抚,造成內(nèi)存泄露。
82倔矾、能不能自己寫個類妄均,也叫java.lang.String柱锹?
可以,但在應(yīng)用的時候丰包,需要用自己的類加載器去加載禁熏,否則,系統(tǒng)的類加載器永遠(yuǎn)只是去加載jre.jar包中的那個java.lang.String烫沙。由于在tomcat的web應(yīng)用程序中匹层,都是由webapp自己的類加載器先自己加載WEB-INF/classess目錄中的類,然后才委托上級的類加載器加載锌蓄,如果我們在tomcat的web應(yīng)用程序中寫一個java.lang.String升筏,這時候Servlet程序加載的就是我們自己寫的java.lang.String莫瞬,但是這么干就會出很多潛在的問題艾猜,原來所有用了java.lang.String類的都將出現(xiàn)問題渡冻。
雖然java提供了endorsed技術(shù)蹦漠,可以覆蓋jdk中的某些類狰闪,具體做法是….揭措。但是败许,能夠被覆蓋的類是有限制范圍怒允,反正不包括java.lang這樣的包中的類柑潦。
(下面的例如主要是便于大家學(xué)習(xí)理解只用享言,不要作為答案的一部分,否則渗鬼,人家懷疑是題目泄露了)例如览露,運(yùn)行下面的程序:
packagejava.lang;
publicclassString {
/**
*@paramargs
*/
public static voidmain(String[] args) {
//TODOAuto-generated method stub
System.out.println("string");
}
}
報告的錯誤如下:
java.lang.NoSuchMethodError:main
Exception inthread "main"
這是因為加載了jre自帶的java.lang.String,而該類中沒有main方法譬胎。
83. Java代碼查錯
1.
abstract class Name {
private String name;
public abstract boolean isStupidName(String name) {}
}
大俠們差牛,這有何錯誤?
答案: 錯。abstract method必須以分號結(jié)尾堰乔,且不帶花括號偏化。
2.
public class Something {
void doSomething () {
private String s = "";
int l = s.length();
}
}
有錯嗎?
答案: 錯。局部變量前不能放置任何訪問修飾符 (private镐侯,public侦讨,和protected)。final可以用來修飾局部變量
(final如同abstract和strictfp苟翻,都是非訪問修飾符搭伤,strictfp只能修飾class和method而非variable)。
3.
abstract class Something {
private abstract String doSomething ();
}
這好像沒什么錯吧?
答案: 錯袜瞬。abstract的methods不能以private修飾。abstract的methods就是讓子類implement(實現(xiàn))具體細(xì)節(jié)的身堡,怎么可以用private把a(bǔ)bstract
method封鎖起來呢? (同理邓尤,abstract method前不能加final)。
4.
public class Something {
public int addOne(final int x) {
return ++x;
}
}
這個比較明顯。
答案: 錯汞扎。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的問題景鼠,這有錯嗎?
答案: 正確。在addOne method中痹扇,參數(shù)o被修飾成final铛漓。如果在addOne method里我們修改了o的reference
(比如: o = new Other();),那么如同上例這題也是錯的鲫构。但這里修改的是o的member vairable
(成員變量)浓恶,而o的reference并沒有改變。
6.
class Something {
int i;
public void doSomething() {
System.out.println("i = "+ i);
}
}
有什么錯呢? 看不出來啊结笨。
答案: 正確包晰。輸出的是"i = 0"。int i屬於instant variable (實例變量炕吸,或叫成員變量)伐憾。instant variable有default value。int的default value是0赫模。
7.
class Something {
final int i;
public void doSomething() {
System.out.println("i = "+ i);
}
}
和上面一題只有一個地方不同树肃,就是多了一個final。這難道就錯了嗎?
答案: 錯嘴瓤。final int i是個final的instant variable (實例變量扫外,或叫成員變量)。final的instant variable沒有default value廓脆,必須在constructor (構(gòu)造器)結(jié)束之前被賦予一個明確的值筛谚。可以修改為"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 ...";
}
}
看上去很完美驾讲。
答案: 錯∠福看上去在main里call doSomething沒有什么問題吮铭,畢竟兩個methods都在同一個class里。但仔細(xì)看颅停,main是static的谓晌。static method不能直接call non-staticmethods悔捶」制浚可改成"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("Dosomething ...");
}
}
這個好像很明顯姐刁。
答案: 正確。從來沒有人說過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();
}
}
答案:錯誤。在編譯時會發(fā)生錯誤(錯誤描述不同的JVM有不同的信息谬俄,意思就是未明確的x調(diào)用柏靶,兩個x都匹配(就象在同時import java.util和java.sql兩個包時直接聲明Date一樣)。對于父類的變量,可以用super.x來明確凤瘦,而接口的屬性默認(rèn)隱含為 public staticfinal.所以可以通過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 = newBall("Football");
System.out.println(ball.getName());
}
}
這個錯誤不容易發(fā)現(xiàn)。
答案: 錯蔬芥。"interfaceRollable extends Playable, Bounceable"沒有問題梆靖。interface可繼承多個interfaces,所以這里沒錯笔诵。問題出在interface Rollable里的"Ball ball =new Ball("PingPang");"返吻。任何在interface里聲明的interface variable (接口變量,也可稱成員變量)乎婿,默認(rèn)為public static final测僵。也就是說"Ball ball = new Ball("PingPang");"實際上是"public staticfinal Ball ball = new Ball("PingPang");"。在Ball類的Play()方法中谢翎,"ball = newBall("Football");"改變了ball的reference捍靠,而這里的ball來自Rollable interface,Rollable interface里的ball是public static final的森逮,final的object是不能被改變reference的榨婆。因此編譯器將在"ball = newBall("Football");"這里顯示有錯。
二.算法與編程
1褒侧、編寫一個程序良风,將a.txt文件中的單詞與b.txt文件中的單詞交替合并到c.txt文件中,a.txt文件中的單詞用回車符分隔闷供,b.txt文件中用回車或空格進(jìn)行分隔烟央。
答:
packagecn.itcast;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
public class MainClass{
public static voidmain(String[] args) throws Exception{
FileManager a= new FileManager("a.txt",new char[]{'\n'});
FileManager b= new FileManager("b.txt",new char[]{'\n',' '});
FileWriter c= new FileWriter("c.txt");
String aWord= null;
String bWord= null;
while((aWord= a.nextWord()) !=null ){
c.write(aWord+ "\n");
bWord= b.nextWord();
if(bWord!= null)
c.write(bWord+ "\n");
}
while((bWord= b.nextWord()) != null){
c.write(bWord+ "\n");
}
c.close();
}
}
class FileManager{
String[] words =null;
int pos = 0;
Public FileManager(String filename,char[] seperators) throws Exception{
File f = new File(filename);
FileReader reader = new FileReader(f);
char[] buf =new char[(int)f.length()];
int len =reader.read(buf);
Stringresults = new String(buf,0,len);
String regex= null;
if(seperators.length>1 ){
regex= "" + seperators[0] + "|" + seperators[1];
}else{
regex= "" + seperators[0];
}
words =results.split(regex);
}
public StringnextWord(){
if(pos ==words.length)
returnnull;
returnwords[pos++];
}
}
2、編寫一個程序歪脏,將d:\java目錄下的所有.java文件復(fù)制到d:\jad目錄下疑俭,并將原來文件的擴(kuò)展名從.java改為.jad。
(大家正在做上面這道題婿失,網(wǎng)上遲到的朋友也請做做這道題钞艇,找工作必須能編寫這些簡單問題的代碼9砑)
答:listFiles方法接受一個FileFilter對象,這個FileFilter對象就是過慮的策略對象香璃,不同的人提供不同的FileFilter實現(xiàn),即提供了不同的過濾策略舟误。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Jad2Java {
public static voidmain(String[] args) throws Exception {
File srcDir =new File("java");
if(!(srcDir.exists()&& srcDir.isDirectory()))
thrownew Exception("目錄不存在");
File[] files= srcDir.listFiles(
newFilenameFilter(){
publicboolean accept(File dir, String name) {
returnname.endsWith(".java");
}
}
);
System.out.println(files.length);
File destDir= new File("jad");
if(!destDir.exists())destDir.mkdir();
for(File f:files){
FileInputStream ?fis = new FileInputStream(f);
StringdestFileName = f.getName().replaceAll("\\.java$", ".jad");
FileOutputStreamfos = new FileOutputStream(new File(destDir,destFileName));
copy(fis,fos);
fis.close();
fos.close();
}
}
private static voidcopy(InputStream ips,OutputStream ops) throws Exception{
int len = 0;
byte[] buf =new byte[1024];
while((len =ips.read(buf)) != -1){
ops.write(buf,0,len);
}
}
}
由本題總結(jié)的思想及策略模式的解析:
1.
class jad2java{
1.得到某個目錄下的所有的java文件集合
1.1得到目錄 File srcDir = newFile("d:\\java");
1.2得到目錄下的所有java文件:File[] files =srcDir.listFiles(new MyFileFilter());
1.3只想得到.java的文件: class MyFileFilterimplememyts FileFilter{
publicboolean accept(File pathname){
returnpathname.getName().endsWith(".java")
}
}
2.將每個文件復(fù)制到另外一個目錄葡秒,并改擴(kuò)展名
2.1得到目標(biāo)目錄,如果目標(biāo)目錄不存在嵌溢,則創(chuàng)建之
2.2根據(jù)源文件名得到目標(biāo)文件名眯牧,注意要用正則表達(dá)式,注意.的轉(zhuǎn)義赖草。
2.3根據(jù)表示目錄的File和目標(biāo)文件名的字符串学少,得到表示目標(biāo)文件的File。
//要在硬盤中準(zhǔn)確地創(chuàng)建出一個文件秧骑,需要知道文件名和文件的目錄版确。
2.4將源文件的流拷貝成目標(biāo)文件流,拷貝方法獨立成為一個方法乎折,方法的參數(shù)采用抽象流的形式绒疗。
//方法接受的參數(shù)類型盡量面向父類,越抽象越好骂澄,這樣適應(yīng)面更寬廣吓蘑。
}
分析listFiles方法內(nèi)部的策略模式實現(xiàn)原理
File[] listFiles(FileFilter filter){
File[] files =listFiles();
//ArraylistacceptedFilesList = new ArrayList();
File[] acceptedFiles= new File[files.length];
int pos = 0;
for(File file:files){
booleanaccepted = filter.accept(file);
if(accepted){
//acceptedFilesList.add(file);
acceptedFiles[pos++]= file;
}
}
Arrays.copyOf(acceptedFiles,pos);
//return(File[])accpetedFilesList.toArray();
}
3、編寫一個截取字符串的函數(shù)坟冲,輸入為一個字符串和字節(jié)數(shù)磨镶,輸出為按字節(jié)截取的字符串,但要保證漢字不被截取半個,如“我ABC”庄敛,4奶浦,應(yīng)該截取“我AB”,輸入“我ABC漢DEF”沸移,6,應(yīng)該輸出“我ABC”侄榴,而不是“我ABC+漢的半個”雹锣。
答:
首先要了解中文字符有多種編碼及各種編碼的特征。
假設(shè)n為要截取的字節(jié)數(shù)癞蚕。
public static voidmain(String[] args) throws Exception{
String str ="我a愛中華abc我愛傳智def';
String str ="我ABC漢";
int num =trimGBK(str.getBytes("GBK"),5);
System.out.println(str.substring(0,num));
}
public staticint ?trimGBK(byte[] buf,int n){
int num = 0;
booleanbChineseFirstHalf = false;
for(inti=0;i
{
if(buf[i]<0&& !bChineseFirstHalf){
bChineseFirstHalf= true;
}else{
num++;
bChineseFirstHalf= false;
}
}
return num;
}
4蕊爵、有一個字符串,其中包含中文字符桦山、英文字符和數(shù)字字符攒射,請統(tǒng)計和打印出各個字符的個數(shù)醋旦。
答:哈哈,其實包含中文字符会放、英文字符饲齐、數(shù)字字符原來是出題者放的煙霧彈。
String content = “中國aadf的111薩bbb菲的zz薩菲”;
HashMap map = new HashMap();
for(int i=0;i
{
char c =content.charAt(i);
Integer num =map.get(c);
if(num == null)
num = 1;
else
num = num +1;
map.put(c,num);
}
for(Map.EntrySet entry : map)
{
system.out.println(entry.getkey()+ “:” + entry.getValue());
}
估計是當(dāng)初面試的那個學(xué)員表述不清楚咧最,問題很可能是:
如果一串字符如"aaaabbc中國1512"要分別統(tǒng)計英文字符的數(shù)量捂人,中文字符的數(shù)量,和數(shù)字字符的數(shù)量矢沿,假設(shè)字符中沒有中文字符滥搭、英文字符、數(shù)字字符之外的其他特殊字符捣鲸。
int engishCount;
int chineseCount;
int digitCount;
for(int i=0;i
{
charch = str.charAt(i);
if(ch>=’0’&& ch<=’9’)
{
digitCount++
}
elseif((ch>=’a’&& ch<=’z’) || (ch>=’A’ && ch<=’Z’))
{
engishCount++;
}
else
{
chineseCount++;
}
}
System.out.println(……………);
5瑟匆、說明生活中遇到的二叉樹,用java實現(xiàn)二叉樹
這是組合設(shè)計模式栽惶。
我有很多個(假設(shè)10萬個)數(shù)據(jù)要保存起來愁溜,以后還需要從保存的這些數(shù)據(jù)中檢索是否存在某個數(shù)據(jù),(我想說出二叉樹的好處媒役,該怎么說呢祝谚?那就是說別人的缺點),假如存在數(shù)組中酣衷,那么交惯,碰巧要找的數(shù)字位于99999那個地方,那查找的速度將很慢穿仪,因為要從第1個依次往后取席爽,取出來后進(jìn)行比較。平衡二叉樹(構(gòu)建平衡二叉樹需要先排序啊片,我們這里就不作考慮了)可以很好地解決這個問題只锻,但二叉樹的遍歷(前序,中序紫谷,后序)效率要比數(shù)組低很多齐饮,原理如下圖:
代碼如下:
packagecom.huawei.interview;
publicclassNode {
public intvalue;
publicNode left;
publicNode right;
public voidstore(intvalue)
{
if(value<this.value)
{
if(left ==null)
{
left =newNode();
left.value=value;
}
else
{
left.store(value);
}
}
else if(value>this.value)
{
if(right ==null)
{
right =newNode();
right.value=value;
}
else
{
right.store(value);
}
}
}
public booleanfind(intvalue)
{
System.out.println("happen" +this.value);
if(value ==this.value)
{
return true;
}
else if(value>this.value)
{
if(right ==null)returnfalse;
returnright.find(value);
}else
{
if(left ==null)returnfalse;
returnleft.find(value);
}
}
public ?voidpreList()
{
System.out.print(this.value+ ",");
if(left!=null)left.preList();
if(right!=null) right.preList();
}
public voidmiddleList()
{
if(left!=null)left.preList();
System.out.print(this.value+ ",");
if(right!=null)right.preList();
}
public voidafterList()
{
if(left!=null)left.preList();
if(right!=null)right.preList();
System.out.print(this.value+ ",");
}
public static voidmain(String [] args)
{
int[] data =new int[20];
for(inti=0;i
{
data[i] = (int)(Math.random()*100)+ 1;
System.out.print(data[i] +",");
}
System.out.println();
Node root =newNode();
root.value = data[0];
for(inti=1;i
{
root.store(data[i]);
}
root.find(data[19]);
root.preList();
System.out.println();
root.middleList();
System.out.println();
root.afterList();
}
}
-----------------又一次臨場寫的代碼---------------------------
importjava.util.Arrays;
importjava.util.Iterator;
public class Node{
private Node left;
private Node right;
private int value;
//private int num;
public Node(int value){
this.value = value;
}
public void add(int value){
if(value > this.value)
{
if(right != null)
right.add(value);
else
{
Node node = new Node(value);
right = node;
}
}
else{
if(left != null)
left.add(value);
else
{
Node node = new Node(value);
left = node;
}
}
}
public boolean find(int value){
if(value == this.value) return true;
else if(value > this.value){
if(right == null) return false;
else return right.find(value);
}else{
if(left == null) return false;
else return left.find(value);
}
}
public void display(){
System.out.println(value);
if(left != null) left.display();
if(right != null) right.display();
}
/*public Iterator iterator(){
}*/
public static void main(String[] args){
int[] values = new int[8];
for(int i=0;i<8;i++){
int num = (int)(Math.random() * 15);
//System.out.println(num);
//if(Arrays.binarySearch(values,num)<0)
if(!contains(values,num))
values[i] = num;
else
i--;
}
System.out.println(Arrays.toString(values));
Node root = new Node(values[0]);
for(int i=1;i
root.add(values[i]);
}
System.out.println(root.find(13));
root.display();
}
public static boolean contains(int [] arr,int value){
int i = 0;
for(;i
if(arr[i] == value) return true;
}
return false;
}
}
6、從類似如下的文本文件中讀取出所有的姓名笤昨,并打印出重復(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)場問也是可以的。還要加上實現(xiàn)思路的注釋):
packagecom.huawei.interview;
importjava.io.BufferedReader;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.util.Comparator;
importjava.util.HashMap;
importjava.util.Iterator;
importjava.util.Map;
importjava.util.TreeSet;
publicclassGetNameTest {
/**
*@paramargs
*/
public static voidmain(String[] args) {
//TODOAuto-generated method stub
//InputStream ips =GetNameTest.class.getResourceAsStream("/com/huawei/interview/info.txt");
//用上一行注釋的代碼和下一行的代碼都可以匕坯,因為info.txt與GetNameTest類在同一包下面束昵,所以,可以用下面的相對路徑形式
Map results =newHashMap();
InputStream ips = GetNameTest.class.getResourceAsStream("info.txt");
BufferedReader in =newBufferedReader(newInputStreamReader(ips));
String line =null;
try{
while((line=in.readLine())!=null)
{
dealLine(line,results);
}
sortResults(results);
}catch(IOException e) {
//TODOAuto-generated catchblock
e.printStackTrace();
}
}
static classUser
{
publicString name;
publicInteger value;
publicUser(String name,Integervalue)
{
this.name = name;
this.value = value;
}
@Override
public booleanequals(Object obj) {
//TODOAuto-generated methodstub
//下面的代碼沒有執(zhí)行葛峻,說明往treeset中增加數(shù)據(jù)時锹雏,不會使用到equals方法。
booleanresult =super.equals(obj);
System.out.println(result);
returnresult;
}
}
private static voidsortResults(Map results) {
//TODOAuto-generated method stub
TreeSet sortedResults =newTreeSet(
newComparator(){
public intcompare(Object o1, Object o2) {
//TODOAuto-generated method stub
User user1 = (User)o1;
User user2 = (User)o2;
/*如果compareTo返回結(jié)果0术奖,則認(rèn)為兩個對象相等逼侦,新的對象不會增加到集合中去
*所以,不能直接用下面的代碼腰耙,否則,那些個數(shù)相同的其他姓名就打印不出來铲球。
* */
//returnuser1.value-user2.value;
//returnuser1.value
if(user1.value
{
return-1;
}else if(user1.value>user2.value)
{
return1;
}else
{
returnuser1.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(newUser(name,value));
}
}
printResults(sortedResults);
}
private static voidprintResults(TreeSet sortedResults)
{
Iterator iterator ?= sortedResults.iterator();
while(iterator.hasNext())
{
User user = (User)iterator.next();
System.out.println(user.name +":" + user.value);
}
}
public static voiddealLine(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);
}
}
}
}
7挺庞、寫一個Singleton出來。
第一種:飽漢模式
public classSingleTon {
private SingleTon(){
}
//實例化放在靜態(tài)代碼塊里可提高程序的執(zhí)行效率稼病,但也可能更占用空間
private final static SingleTon instance =new SingleTon();
public static SingleTon getInstance(){
return instance;
}
}
第二種:饑漢模式
public classSingleTon {
private SingleTon(){}
private static instance = null;//newSingleTon();
public static synchronized SingleTongetInstance(){
if(instance == null)
instance = new SingleTon();
return instance;
}
}
第三種:用枚舉
public enum SingleTon{
ONE;
}
第三:更實際的應(yīng)用(在什么情況用單例)
public classSequenceGenerator{
//下面是該類自身的業(yè)務(wù)功能代碼
private int count = 0;
public synchronized int getSequence(){
++count;
}
//下面是把該類變成單例的代碼
private SequenceGenerator(){}
private final static instance = newSequenceGenerator();
public static SingleTon getInstance(){
return instance;
}
}
第四:
public class MemoryDao
{
private HashMap map = new HashMap();
publicvoid add(Student stu1){
map.put(SequenceGenerator.getInstance().getSequence(),stu1);
}
//把MemoryDao變成單例
}
Singleton模式主要作用是保證在Java應(yīng)用程序中选侨,一個類Class只有一個實例存在。
一般Singleton模式通常有幾種種形式:
第一種形式: 定義一個類,它的構(gòu)造函數(shù)為private的,它有一個static的private的該類變量梆奈,在類初始化時實例話锭魔,通過一個public的getInstance方法獲取對它的引用,繼而調(diào)用其中的方法。
public class Singleton {
private Singleton(){}
//在自己內(nèi)部定義自己一個實例嘉赎,是不是很奇怪?
//注意這是private只供內(nèi)部調(diào)用
private staticSingleton instance = new Singleton();
//這里提供了一個供外部訪問本class的靜態(tài)方法,可以直接訪問
public staticSingleton getInstance() {
return instance;
}
}
第二種形式:
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//這個方法比上面有所改進(jìn)洪己,不用每次都進(jìn)行生成對象,只是第一次
//使用時生成實例竟贯,提高了效率答捕!
if (instance==null)
instance=new Singleton();
return instance;
}
}
其他形式:
定義一個類,它的構(gòu)造函數(shù)為private的屑那,所有方法為static的拱镐。
一般認(rèn)為第一種形式要更加安全些
8、遞歸算法題1
一個整數(shù)持际,大于0沃琅,不用循環(huán)和本地變量,按照n选酗,2n阵难,4n,8n的順序遞增芒填,當(dāng)值大于5000時呜叫,把值按照指定順序輸出來空繁。
例:n=1237
則輸出為:
1237,
2474朱庆,
4948盛泡,
9896,
9896娱颊,
4948傲诵,
2474,
1237箱硕,
提示:寫程序時拴竹,先致謝按遞增方式的代碼,寫好遞增的以后剧罩,再增加考慮遞減部分栓拜。
public static void doubleNum(int n)
{
System.out.println(n);
if(n<=5000)
doubleNum(n*2);
System.out.println(n);
}
Gaibaota(N) = Gaibaota(N-1) + n
9、遞歸算法題2
第1個人10惠昔,第2個比第1個人大2歲幕与,依次遞推,請用遞歸方式計算出第8個人多大镇防?
packagecn.itcast;
importjava.util.Date;
publicclassA1 {
public static voidmain(String [] args)
{
System.out.println(computeAge(8));
}
public static intcomputeAge(intn)
{
if(n==1)return10;
returncomputeAge(n-1) + 2;
}
}
public static voidtoBinary(intn,StringBuffer result)
{
if(n/2 != 0)
toBinary(n/2,result);
result.append(n%2);
}
10啦鸣、排序都有哪幾種方法?請列舉来氧。用JAVA實現(xiàn)一個快速排序诫给。
本人只研究過冒泡排序、選擇排序和快速排序啦扬,下面是快速排序的代碼:
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
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)兩者交錯時停止
if(i
quickSort(strDate,i,right);//從
}
if(j>left){
quickSort(strDate,left,j);
}
}
/**
* @param args
*/
public static void main(String[] args){
String[] strVoid=newString[]{"11","66","22","0","55","22","0","32"};
QuickSort sort=new QuickSort();
sort.quickSort(strVoid,0,strVoid.length-1);
for(int i=0;i
System.out.println(strVoid[i]+" ");
}
}
}
11蝙搔、有數(shù)組a[n],用java代碼將數(shù)組元素順序顛倒
//用下面的也可以
//for(inti=0,int j=a.length-1;i
importjava.util.Arrays;
public classSwapDemo{
public static void main(String[] args){
int [] a = new int[]{
(int)(Math.random() *1000),
(int)(Math.random() * 1000),
(int)(Math.random() *1000),
(int)(Math.random() *1000),
(int)(Math.random() * 1000)
};
System.out.println(a);
System.out.println(Arrays.toString(a));
swap(a);
System.out.println(Arrays.toString(a));
}
public static void swap(int a[]){
int len = a.length;
for(int i=0;i
int tmp = a[i];
a[i] = a[len-1-i];
a[len-1-i] = tmp;
}
}
}
12.金額轉(zhuǎn)換考传,阿拉伯?dāng)?shù)字的金額轉(zhuǎn)換成中國傳統(tǒng)的形式如:(¥1011)->(一千零一拾一元整)輸出吃型。
去零的代碼:
returnsb.reverse().toString().replaceAll("零[拾佰仟]","零").replaceAll("零+萬","萬").replaceAll("零+元","元").replaceAll("零+","零");
public class RenMingBi {
/**
* @param args add by zxx ,Nov 29, 2008
*/
private static finalchar[] data = new char[]{
'零','壹','貳','叁','肆','伍','陸','柒','捌','玖'
};
private static finalchar[] units = new char[]{
'元','拾','佰','仟','萬','拾','佰','仟','億'
};
public static voidmain(String[] args) {
// TODOAuto-generated method stub
System.out.println(
convert(135689123));
}
public static Stringconvert(int money)
{
StringBuffersbf = new StringBuffer();
int unit = 0;
while(money!=0)
{
sbf.insert(0,units[unit++]);
intnumber = money%10;
sbf.insert(0,data[number]);
money/= 10;
}
returnsbf.toString();
}
}
三. html&JavaScript&ajax部分
1. 判斷第二個日期比第一個日期大
如何用腳本判斷用戶輸入的的字符串是下面的時間格式2004-11-21必須要保證用戶的輸入是此格式,并且是時間僚楞,比如說月份不大于12等等勤晚,另外我需要用戶輸入兩個,并且后一個要比前一個晚泉褐,只允許用JAVASCRIPT赐写,請詳細(xì)幫助作答,,
//這里可用正則表達(dá)式判斷提前判斷一下格式膜赃,然后按下提取各時間字段內(nèi)容
window.onload =function()
{
//這么寫是為了實現(xiàn)js代碼與html代碼的分離挺邀,當(dāng)我修改js時,不能影響html代碼。
document.getElementById("frm1").onsubmit=
function(){
vard1 = this.d1.value;
vard2 = this.d2.value;
if(!verifyDate(d1)) {alert("第一個日期格式不對");return false;}
if(!verifyDate(d2)) {alert("第二個日期格式不對");return false;}
if(!compareDate(d1,d2)){alert("第二個日期比第一日期小");return false;}
};
}
functioncompareDate(d1,d2)
{
var arrayD1= d1.split("-");
var date1 =new Date(arrayD1[0],arrayD1[1],arrayD1[2]);
var arrayD2= d2.split("-");
var date2 =new Date(arrayD2[0],arrayD2[1],arrayD2[2]);
if(date1> date2) return false;
return true;
}
functionverifyDate(d)
{
vardatePattern = /^\d{4}-(0?[1-9]|1[0-2])-(0?[1-9]|[1-2]\d|3[0-1])$/;
returndatePattern.test(d);
}
2. 用table顯示n條記錄端铛,每3行換一次顏色泣矛,即1,2禾蚕,3用紅色字體您朽,4,5换淆,6用綠色字體哗总,7,8倍试,9用紅顏色字體革娄。
1
2
3
4
5
6
7
8
9
10
window.onload=function()
{
var tbl =document.getElementById("tbl");
rows =tbl.getElementsByTagName("tr");
for(i=0;i
{
var j= parseInt(i/3);
if(j%2==0)rows[i].style.backgroundColor="#f00";
else ?rows[i].style.backgroundColor="#0f0";
}
}
3柄驻、HTML的 form提交之前如何驗證數(shù)值文本框的內(nèi)容全部為數(shù)字?否則的話提示用戶并終止提交?
function chkForm(this)
{
var value = thist.d1.value;
var len =value.length;
for(vari=0;i
{
if(value.charAt(i)>"9"|| value.charAt(i)<"0")
{
alert("含有非數(shù)字字符");
returnfalse;
}
}
return true;
}
4击孩、請寫出用于校驗HTML文本框中輸入的內(nèi)容全部為數(shù)字的javascript代碼
function chkNumber(eleText)
{
var value =eleText.value;
var len =value.length;
for(vari=0;i
{
if(value.charAt(i)>"9"|| value.charAt(i)<"0")
{
alert("含有非數(shù)字字符");
eleText.focus();
break;
}
}
}
除了寫完代碼晾匠,還應(yīng)該在網(wǎng)頁上寫出實驗步驟和在代碼中加入實現(xiàn)思路,讓面試官一看就明白你的意圖和檢查你的結(jié)果准颓。
5、說說你用過那些ajax技術(shù)和框架棺妓,說說它們的區(qū)別
四. Java web部分
1攘已、Tomcat的優(yōu)化經(jīng)驗
答:去掉對web.xml的監(jiān)視,把jsp提前編輯成Servlet怜跑。
有富余物理內(nèi)存的情況样勃,加大tomcat使用的jvm的內(nèi)存
2、HTTP請求的GET與POST方式的區(qū)別
答:servlet有良好的生存期的定義性芬,包括加載和實例化峡眶、初始化、處理請求以及服務(wù)結(jié)束植锉。這個生存期由javax.servlet.Servlet接口的init,service和destroy方法表達(dá)辫樱。
3、解釋一下什么是servlet;
答:servlet有良好的生存期的定義俊庇,包括加載和實例化狮暑、初始化、處理請求以及服務(wù)結(jié)束辉饱。這個生存期由javax.servlet.Servlet接口的init,service和destroy方法表達(dá)搬男。
4、說一說Servlet的生命周期?
答:servlet有良好的生存期的定義彭沼,包括加載和實例化缔逛、初始化、處理請求以及服務(wù)結(jié)束。這個生存期由javax.servlet.Servlet接口的init,service和destroy方法表達(dá)褐奴。
Servlet被服務(wù)器實例化后按脚,容器運(yùn)行其init方法,請求到達(dá)時運(yùn)行其service方法歉糜,service方法自動派遣運(yùn)行與請求對應(yīng)的doXXX方法(doGet乘寒,doPost)等,當(dāng)服務(wù)器決定將實例銷毀的時候調(diào)用其destroy方法匪补。
web容器加載servlet伞辛,生命周期開始。通過調(diào)用servlet的init()方法進(jìn)行servlet的初始化夯缺。通過調(diào)用service()方法實現(xiàn)蚤氏,根據(jù)請求的不同調(diào)用不同的do***()方法。結(jié)束服務(wù)踊兜,web容器調(diào)用servlet的destroy()方法竿滨。
5、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 {
}
}
6捏境、SERVLET API中forward()與redirect()的區(qū)別于游?
答:前者僅是容器中控制權(quán)的轉(zhuǎn)向,在客戶端瀏覽器地址欄中不會顯示出轉(zhuǎn)向后的地址垫言;后者則是完全的跳轉(zhuǎn)贰剥,瀏覽器將會得到跳轉(zhuǎn)的地址,并重新發(fā)送請求鏈接筷频。這樣蚌成,從瀏覽器的地址欄中可以看到跳轉(zhuǎn)后的鏈接地址。所以凛捏,前者更加高效担忧,在前者可以滿足需要時,盡量使用forward()方法坯癣,并且瓶盛,這樣也有助于隱藏實際的鏈接。在有些情況下示罗,比如蓬网,需要跳轉(zhuǎn)到一個其它服務(wù)器上的資源,則必須使用
sendRedirect()方法鹉勒。
7帆锋、什么情況下調(diào)用doGet()和doPost()?
Jsp頁面中的FORM標(biāo)簽里的method屬性為get時調(diào)用doGet()禽额,為post時調(diào)用doPost()锯厢。
8皮官、Request對象的主要方法:
setAttribute(String name,Object):設(shè)置名字為name的request的參數(shù)值
getAttribute(String name):返回由name指定的屬性值
getAttributeNames():返回request對象所有屬性的名字集合,結(jié)果是一個枚舉的實例
getCookies():返回客戶端的所有Cookie對象实辑,結(jié)果是一個Cookie數(shù)組
getCharacterEncoding():返回請求中的字符編碼方式
getContentLength():返回請求的Body的長度
getHeader(String name):獲得HTTP協(xié)議定義的文件頭信息
getHeaders(String name):返回指定名字的request Header的所有值捺氢,結(jié)果是一個枚舉的實例
getHeaderNames():返回所以request Header的名字,結(jié)果是一個枚舉的實例
getInputStream():返回請求的輸入流剪撬,用于獲得請求中的數(shù)據(jù)
getMethod():獲得客戶端向服務(wù)器端傳送數(shù)據(jù)的方法
getParameter(String name):獲得客戶端傳送給服務(wù)器端的有name指定的參數(shù)值
getParameterNames():獲得客戶端傳送給服務(wù)器端的所有參數(shù)的名字卿啡,結(jié)果是一個枚舉的實例
getParametervalues(String name):獲得有name指定的參數(shù)的所有值
getProtocol():獲取客戶端向服務(wù)器端傳送數(shù)據(jù)所依據(jù)的協(xié)議名稱
getQueryString():獲得查詢字符串
getRequestURI():獲取發(fā)出請求字符串的客戶端地址
getRemoteAddr():獲取客戶端的IP地址
getRemoteHost():獲取客戶端的名字
getSession([Boolean create]):返回和請求相關(guān)Session
getServerName():獲取服務(wù)器的名字
getServletPath():獲取客戶端所請求的腳本文件的路徑
getServerPort():獲取服務(wù)器的端口號
removeAttribute(String name):刪除請求中的一個屬性
9亡呵、forward和redirect的區(qū)別
forward是服務(wù)器請求資源,服務(wù)器直接訪問目標(biāo)地址的URL,把那個URL的響應(yīng)內(nèi)容讀取過來萤捆,然后把這些內(nèi)容再發(fā)給瀏覽器魄健,瀏覽器根本不知道服務(wù)器發(fā)送的內(nèi)容是從哪兒來的乏矾,所以它的地址欄中還是原來的地址僚饭。
redirect就是服務(wù)端根據(jù)邏輯,發(fā)送一個狀態(tài)碼,告訴瀏覽器重新去請求那個地址,一般來說瀏覽器會用剛才請求的所有參數(shù)重新請求疫诽,所以session,request參數(shù)都可以獲取舅世。
10、request.getAttribute()和 request.getParameter()有何區(qū)別?
11. jsp有哪些內(nèi)置對象?作用分別是什么?分別有什么方法奇徒?
答:JSP共有以下9個內(nèi)置的對象:
request 用戶端請求雏亚,此請求會包含來自GET/POST請求的參數(shù)
response 網(wǎng)頁傳回用戶端的回應(yīng)
pageContext 網(wǎng)頁的屬性是在這里管理
session 與請求有關(guān)的會話期
application servlet 正在執(zhí)行的內(nèi)容
out 用來傳送回應(yīng)的輸出
configservlet的構(gòu)架部件
page JSP網(wǎng)頁本身
exception 針對錯誤網(wǎng)頁,未捕捉的例外
request表示HttpServletRequest對象摩钙。它包含了有關(guān)瀏覽器請求的信息罢低,并且提供了幾個用于獲取cookie, header,和session數(shù)據(jù)的有用的方法。
response表示HttpServletResponse對象腺律,并提供了幾個用于設(shè)置送回瀏覽器的響應(yīng)的方法(如cookies,頭信息等)
out對象是javax.jsp.JspWriter的一個實例,并提供了幾個方法使你能用于向瀏覽器回送輸出結(jié)果宜肉。
pageContext表示一個javax.servlet.jsp.PageContext對象匀钧。它是用于方便存取各種范圍的名字空間、servlet相關(guān)的對象的API谬返,并且包裝了通用的servlet相關(guān)功能的方法之斯。
session表示一個請求的javax.servlet.http.HttpSession對象。Session可以存貯用戶的狀態(tài)信息
applicaton表示一個javax.servle.ServletContext對象遣铝。這有助于查找有關(guān)servlet引擎和servlet環(huán)境的信息
config表示一個javax.servlet.ServletConfig對象佑刷。該對象用于存取servlet實例的初始化參數(shù)。
page表示從該頁面產(chǎn)生的一個servlet實例
12. jsp有哪些動作?作用分別是什么?
(這個問題似乎不重要酿炸,不明白為何有此題)
答:JSP共有以下6種基本動作
jsp:include:在頁面被請求的時候引入一個文件瘫絮。
jsp:useBean:尋找或者實例化一個JavaBean。
jsp:setProperty:設(shè)置JavaBean的屬性填硕。
jsp:getProperty:輸出某個JavaBean的屬性麦萤。
jsp:forward:把請求轉(zhuǎn)到一個新的頁面鹿鳖。
jsp:plugin:根據(jù)瀏覽器類型為Java插件生成OBJECT或EMBED標(biāo)記
13、JSP的常用指令
isErrorPage(是否能使用Exception對象)壮莹,isELIgnored(是否忽略表達(dá)式)
14. JSP中動態(tài)INCLUDE與靜態(tài)INCLUDE的區(qū)別翅帜?
答:動態(tài)INCLUDE用jsp:include動作實現(xiàn)
它總是會檢查所含文件中的變化,適合用于包含動態(tài)頁面命满,并且可以帶參數(shù) 靜態(tài)INCLUDE用include偽碼實現(xiàn),定不會檢查所含文件的變化涝滴,適用于包含靜態(tài)頁面 <%@include file=included.htm %>
15、兩種跳轉(zhuǎn)方式分別是什么?有什么區(qū)別?
(下面的回答嚴(yán)重錯誤胶台,應(yīng)該是想問forward和sendRedirect的區(qū)別歼疮,畢竟出題的人不是專業(yè)搞文字藝術(shù)的人,可能表達(dá)能力并不見得很強(qiáng)概作,用詞不一定精準(zhǔn)腋妙,加之其自身的技術(shù)面也可能存在一些問題,不一定真正將他的意思表達(dá)清楚了讯榕,嚴(yán)格意思上來講骤素,一些題目可能根本就無人能答,所以愚屁,答題時要掌握主動济竹,只要把自己知道的表達(dá)清楚就夠了,而不要去推敲原始題目的具體含義是什么霎槐,不要一味想著是在答題)
答:有兩種送浊,分別為:
前者頁面不會轉(zhuǎn)向include所指的頁面,只是顯示該頁的結(jié)果丘跌,主頁面還是原來的頁面袭景。執(zhí)行完后還會回來,相當(dāng)于函數(shù)調(diào)用闭树。并且可以帶參數(shù).后者完全轉(zhuǎn)向新頁面耸棒,不會再回來。相當(dāng)于go to 語句报辱。
16与殃、頁面間對象傳遞的方法
request,session碍现,application幅疼,cookie等
17、JSP和Servlet有哪些相同點和不同點昼接,他們之間的聯(lián)系是什么爽篷?
JSP是Servlet技術(shù)的擴(kuò)展,本質(zhì)上是Servlet的簡易方式慢睡,更強(qiáng)調(diào)應(yīng)用的外表表達(dá)漾脂。JSP編譯后是"類servlet"。Servlet和JSP最主要的不同點在于九火,Servlet的應(yīng)用邏輯是在Java文件中,并且完全從表示層中的HTML里分離開來佃却。而JSP的情況是Java和HTML可以組合成一個擴(kuò)展名為.jsp的文件。JSP側(cè)重于視圖窘俺,Servlet主要用于控制邏輯饲帅。
18、MVC的各個部分都有那些技術(shù)來實現(xiàn)?如何實現(xiàn)?
答:MVC是Model-View-Controller的簡寫瘤泪。Model代表的是應(yīng)用的業(yè)務(wù)邏輯(通過JavaBean灶泵,EJB組件實現(xiàn)),View是應(yīng)用的表示面(由JSP頁面產(chǎn)生)对途,Controller是提供應(yīng)用的處理過程控制(一般是一個Servlet)赦邻,通過這種設(shè)計模型把應(yīng)用邏輯,處理過程和顯示邏輯分成不同的組件實現(xiàn)实檀。這些組件可以進(jìn)行交互和重用惶洲。
19、我們在web應(yīng)用開發(fā)過程中經(jīng)常遇到輸出某種編碼的字符膳犹,如iso8859-1等恬吕,如何輸出一個某種編碼的字符串?
Public String translate(String str) {
String tempStr ="";
try {
tempStr = newString(str.getBytes("ISO-8859-1"), "GBK");
tempStr =tempStr.trim();
}
catch (Exception e) {
System.err.println(e.getMessage());
}
return tempStr;
}
20.現(xiàn)在輸入n個數(shù)字须床,以逗號铐料,分開;然后可選擇升或者降序排序豺旬;按提交鍵就在另一頁面顯示按什么排序钠惩,結(jié)果為,提供reset
五.數(shù)據(jù)庫部分
1族阅、用兩種方式根據(jù)部門號從高到低篓跛,工資從低到高列出每個員工的信息。
employee:
eid,ename,salary,deptid;
select * from employeeorder by deptid desc,salary
2耘分、列出各個部門中工資高于本部門的平均工資的員工數(shù)和部門號举塔,并按部門號排序
創(chuàng)建表:
mysql> createtable employee921(id int primary key auto_increment,name varchar(5
0),salary bigint,deptid int);
插入實驗數(shù)據(jù):
mysql> insert into employee921values(null,'zs',1000,1),(null,'ls',1100,1),(null
,'ww',1100,1),(null,'zl',900,1) ,(null,'zl',1000,2), (null,'zl',900,2),(null,'z
l',1000,2) , (null,'zl',1100,2);
編寫sql語句:
()select avg(salary) from employee921 group by deptid;
()mysql> selectemployee921.id,employee921.name,employee921.salary,employee921.dep
tid tid fromemployee921where salary > (select avg(salary) from employee921 where ?deptid = tid);
效率低的一個語句绑警,僅供學(xué)習(xí)參考使用(在group by之后不能使用where求泰,只能使用having,在group by之前可以使用where计盒,即表示對過濾后的結(jié)果分組):
mysql> selectemployee921.id,employee921.name,employee921.salary,employee921.dep
tid tid fromemployee921where salary > (select avg(salary) from employee921 group by deptid havingdeptid = tid);
()select count(*) ,tid
from (
selectemployee921.id,employee921.name,employee921.salary,employee921.deptid tid
from ? ? ?employee921
where salary>
(selectavg(salary) from employee921 where deptid = tid)
) as t
group by tid ;
另外一種方式:關(guān)聯(lián)查詢
select a.ename,a.salary,a.deptid
from emp a,
(selectdeptd,avg(salary) avgsal from emp group by deptid ) b
where a.deptid=b.deptidand a.salary>b.avgsal;
3渴频、存儲過程與觸發(fā)器必須講,經(jīng)常被面試到?
create procedure insert_Student (_name varchar(50),_age int ,out_id int)
begin
insert into studentvalue(null,_name,_age);
select max(stuId)into _id from student;
end;
call insert_Student('wfz',23,@id);
select @id;
mysql> create trigger update_Student BEFORE update on studentFOR EACH ROW
-> select * from student;
觸發(fā)器不允許返回結(jié)果
create trigger update_StudentBEFORE update on student FOR EACH ROW
insert intostudent value(null,'zxx',28);
mysql的觸發(fā)器目前不能對當(dāng)前表進(jìn)行操作
create trigger update_StudentBEFORE update on student FOR EACH ROW
delete from articleswhere id=8;
這個例子不是很好北启,最好是用刪除一個用戶時卜朗,順帶刪除該用戶的所有帖子
這里要注意使用OLD.id
觸發(fā)器用處還是很多的拔第,比如校內(nèi)網(wǎng)、開心網(wǎng)场钉、Facebook蚊俺,你發(fā)一個日志,自動通知好友逛万,其實就是在增加日志時做一個后觸發(fā)泳猬,再向通知表中寫入條目。因為觸發(fā)器效率高宇植。而UCH沒有用觸發(fā)器得封,效率和數(shù)據(jù)處理能力都很低。
存儲過程的實驗步驟:
mysql> delimiter |
mysql> create procedure insertArticle_Procedure (pTitle varchar(50),pBid int,out
pId int)
-> begin
-> insert into article1value(null,pTitle,pBid);
-> select max(id) into pId fromarticle1;
-> end;
-> |
Query OK, 0 rows affected (0.05sec)
mysql> callinsertArticle_Procedure('傳智播客',1,@pid);
-> |
Query OK, 0 rows affected (0.00sec)
mysql> delimiter ;
mysql> select @pid;
+------+
| @pid |
+------+
| 3|
+------+
1 row in set (0.00 sec)
mysql> select * fromarticle1;
+----+--------------+------+
| id | title| bid |
+----+--------------+------+
| 1| test ? ? ? ?| 1 ? ?|
| 2| chuanzhiboke | 1 ? ?|
| 3|傳智播客| 1 ? ?|
+----+--------------+------+
3 rows in set (0.00 sec)
觸發(fā)器的實驗步驟:
create table board1(id intprimary key auto_increment,name varchar(50),ar
ticleCount int);
create table article1(id intprimary key auto_increment,title varchar(50)
,bid int referencesboard1(id));
delimiter |
create triggerinsertArticle_Trigger after insert on article1 for each ro
w begin
-> update board1 setarticleCount=articleCount+1 where id= NEW.bid;
-> end;
-> |
delimiter ;
insert into board1 value(null,'test',0);
insert into article1value(null,'test',1);
還有指郁,每插入一個帖子忙上,都希望將版面表中的最后發(fā)帖時間,帖子總數(shù)字段進(jìn)行同步更新闲坎,用觸發(fā)器做效率就很高疫粥。下次課設(shè)計這樣一個案例,寫觸發(fā)器時箫柳,對于最后發(fā)帖時間可能需要用declare方式聲明一個變量手形,或者是用NEW.posttime來生成。
4悯恍、數(shù)據(jù)庫三范式是什么?
第一范式(1NF):字段具有原子性,不可再分库糠。所有關(guān)系型數(shù)據(jù)庫系統(tǒng)都滿足第一范式)
數(shù)據(jù)庫表中的字段都是單一屬性的,不可再分涮毫。例如瞬欧,姓名字段,其中的姓和名必須作為一個整體罢防,無法區(qū)分哪部分是姓艘虎,哪部分是名,如果要區(qū)分出姓和名咒吐,必須設(shè)計成兩個獨立的字段野建。
第二范式(2NF):
第二范式(2NF)是在第一范式(1NF)的基礎(chǔ)上建立起來的,即滿足第二范式(2NF)必須先滿足第一范式(1NF)恬叹。
要求數(shù)據(jù)庫表中的每個實例或行必須可以被惟一地區(qū)分候生。通常需要為表加上一個列鸥印,以存儲各個實例的惟一標(biāo)識镰踏。這個惟一屬性列被稱為主關(guān)鍵字或主鍵。
第二范式(2NF)要求實體的屬性完全依賴于主關(guān)鍵字搀缠。所謂完全依賴是指不能存在僅依賴主關(guān)鍵字一部分的屬性硅确,如果存在目溉,那么這個屬性和主關(guān)鍵字的這一部分應(yīng)該分離出來形成一個新的實體明肮,新實體與原實體之間是一對多的關(guān)系。為實現(xiàn)區(qū)分通常需要為表加上一個列缭付,以存儲各個實例的惟一標(biāo)識柿估。簡而言之,第二范式就是非主屬性非部分依賴于主關(guān)鍵字陷猫。
第三范式的要求如下:
滿足第三范式(3NF)必須先滿足第二范式(2NF)官份。簡而言之,第三范式(3NF)要求一個數(shù)據(jù)庫表中不包含已在其它表中已包含的非主關(guān)鍵字信息烙丛。
所以第三范式具有如下特征:
1舅巷,每一列只有一個值
2,每一行都能區(qū)分河咽。
3钠右,每一個表都不包含其他表已經(jīng)包含的非主關(guān)鍵字信息。
例如忘蟹,帖子表中只能出現(xiàn)發(fā)帖人的id飒房,而不能出現(xiàn)發(fā)帖人的id,還同時出現(xiàn)發(fā)帖人姓名媚值,否則狠毯,只要出現(xiàn)同一發(fā)帖人id的所有記錄,它們中的姓名部分都必須嚴(yán)格保持一致褥芒,這就是數(shù)據(jù)冗余嚼松。
5、說出一些數(shù)據(jù)庫優(yōu)化方面的經(jīng)驗?
用PreparedStatement一般來說比Statement性能高:一個sql發(fā)給服務(wù)器去執(zhí)行锰扶,涉及步驟:語法檢查献酗、語義分析,編譯坷牛,緩存
“inert into user values(1,1,1)”-à二進(jìn)制
“inert into user values(2,2,2)”-à二進(jìn)制
“inert into user values(?,?,?)”-à二進(jìn)制
有外鍵約束會影響插入和刪除性能罕偎,如果程序能夠保證數(shù)據(jù)的完整性,那在設(shè)計數(shù)據(jù)庫時就去掉外鍵京闰。(比喻:就好比免檢產(chǎn)品颜及,就是為了提高效率,充分相信產(chǎn)品的制造商)
(對于hibernate來說蹂楣,就應(yīng)該有一個變化:empleyee->Deptment對象俏站,現(xiàn)在設(shè)計時就成了employeeàdeptid)
看mysql幫助文檔子查詢章節(jié)的最后部分,例如捐迫,根據(jù)掃描的原理乾翔,下面的子查詢語句要比第二條關(guān)聯(lián)查詢的效率高:
1.select e.name,e.salarywhere e.managerid=(select id from employee where name='zxx');
2.select e.name,e.salary,m.name,m.salary fromemployees e,employees m where
e.managerid = m.id andm.name='zxx';
表中允許適當(dāng)冗余爱葵,譬如施戴,主題帖的回復(fù)數(shù)量和最后回復(fù)時間等
將姓名和密碼單獨從用戶表中獨立出來反浓。這可以是非常好的一對一的案例喲!
sql語句全部大寫赞哗,特別是列名和表名都大寫雷则。特別是sql命令的緩存功能,更加需要統(tǒng)一大小寫肪笋,sql語句à發(fā)給oracle服務(wù)器à語法檢查和編譯成為內(nèi)部指令à緩存和執(zhí)行指令月劈。根據(jù)緩存的特點,不要拼湊條件藤乙,而是用?和PreparedStatment
還有索引對查詢性能的改進(jìn)也是值得關(guān)注的猜揪。
備注:下面是關(guān)于性能的討論舉例
4航班 3個城市
m*n
select * from flight,city where flight.startcityid=city.cityidand city.name='beijing';
m + n
select * from flight where startcityid = (select cityid fromcity where cityname='beijing');
select flight.id,'beijing',flight.flightTime from flight wherestartcityid = (select cityid from city where cityname='beijing')
6、union和union all有什么不同?
假設(shè)我們有一個表Student坛梁,包括以下字段與數(shù)據(jù):
drop table student;
create table student
(
id int primary key,
name nvarchar2(50) not null,
score number not null
);
insert into student values(1,'Aaron',78);
insert into student values(2,'Bill',76);
insert into student values(3,'Cindy',89);
insert into student values(4,'Damon',90);
insert into student values(5,'Ella',73);
insert into student values(6,'Frado',61);
insert into student values(7,'Gill',99);
insert into student values(8,'Hellen',56);
insert into student values(9,'Ivan',93);
insert into student values(10,'Jay',90);
commit;
Union和Union All的區(qū)別而姐。
select *
from student
where id < 4
union
select *
from student
where id > 2 and id < 6
結(jié)果將是
1 ? ?Aaron ? ?78
2 ? ?Bill ? ?76
3 ? ?Cindy ? ?89
4 ? ?Damon ? ?90
5 ? ?Ella ? ?73
如果換成Union All連接兩個結(jié)果集,則返回結(jié)果是:
1 ? ?Aaron ? ?78
2 ? ?Bill ? ?76
3 ? ?Cindy ? ?89
3 ? ?Cindy ? ?89
4 ? ?Damon ? ?90
5 ? ?Ella ? ?73
可以看到划咐,Union和Union All的區(qū)別之一在于對重復(fù)結(jié)果的處理拴念。
UNION在進(jìn)行表鏈接后會篩選掉重復(fù)的記錄,所以在表鏈接后會對所產(chǎn)生的結(jié)果集進(jìn)行排序運(yùn)算褐缠,刪除重復(fù)的記錄再返回結(jié)果政鼠。實際大部分應(yīng)用中是不會產(chǎn)生重復(fù)的記錄,最常見的是過程表與歷史表UNION队魏。如:
select * from gc_dfys
union
select * from ls_jg_dfys
這個SQL在運(yùn)行時先取出兩個表的結(jié)果公般,再用排序空間進(jìn)行排序刪除重復(fù)的記錄,最后返回結(jié)果集胡桨,如果表數(shù)據(jù)量大的話可能會導(dǎo)致用磁盤進(jìn)行排序俐载。
而UNION ALL只是簡單的將兩個結(jié)果合并后就返回。這樣登失,如果返回的兩個結(jié)果集中有重復(fù)的數(shù)據(jù)遏佣,那么返回的結(jié)果集就會包含重復(fù)的數(shù)據(jù)了。
從效率上說揽浙,UNION ALL要比UNION快很多截酷,所以扩氢,如果可以確認(rèn)合并的兩個結(jié)果集中不包含重復(fù)的數(shù)據(jù)的話,那么就使用UNION ALL,
7.分頁語句
取出sql表中第31到40的記錄(以自動增長ID為主鍵)
sql server方案1:
selecttop 10 * from t where id not in (select top 30 id from t order by id ) orde byid
sql server方案2:
selecttop 10 * from t where id in (select top 40 id from t order by id) order by iddesc
mysql方案:select * from t order by idlimit 30,10
oracle方案:select * from (select rownum r,* from t where r<=40) wherer>30
--------------------待整理進(jìn)去的內(nèi)容-------------------------------------
pageSize=20;
pageNo = 5;
1.分頁技術(shù)1(直接利用sql語句進(jìn)行分頁叹螟,效率最高和最推薦的)
mysql:sql = "select * from articles limit " +(pageNo-1)*pageSize + "," + pageSize;
oracle: sql = "select * from " +
"(selectrownum r,* from " +
"(select* from articles order by postime desc)" +
"whererownum<= " + pageNo*pageSize +") tmp " +
"wherer>" + (pageNo-1)*pageSize;
注釋:第7行保證rownum的順序是確定的,因為oracle的索引會造成rownum返回不同的值
簡洋提示:沒有order by時普舆,rownum按順序輸出帐萎,一旦有了order by,rownum不按順序輸出了,這說明rownum是排序前的編號账月。如果對order by從句中的字段建立了索引综膀,那么,rownum也是按順序輸出的局齿,因為這時候生成原始的查詢結(jié)果集時會參照索引表的順序來構(gòu)建剧劝。
sqlserver:sql = "select top 10 * from id not id(select top" + (pageNo-1)*pageSize + "id from articles)"
DataSource ds = new InitialContext().lookup(jndiurl);
Connection cn = ds.getConnection();
//"select * from user where id=?"--->binary directive
PreparedStatement pstmt = cn.prepareSatement(sql);
ResultSet rs = pstmt.executeQuery()
while(rs.next())
{
out.println(rs.getString(1));
}
2.不可滾動的游標(biāo)
pageSize=20;
pageNo = 5;
cn = null
stmt = null;
rs = null;
try
{
sqlserver:sql = "select* from articles";
DataSource ds = new InitialContext().lookup(jndiurl);
Connection cn = ds.getConnection();
//"select * from user where id=?"--->binary directive
PreparedStatement pstmt = cn.prepareSatement(sql);
ResultSet rs = pstmt.executeQuery()
for(int j=0;j<(pageNo-1)*pageSize;j++)
{
rs.next();
}
int i=0;
while(rs.next() && i<10)
{
i++;
out.println(rs.getString(1));
}
}
cacth(){}
finnaly
{
if(rs!=null)try{rs.close();}catch(Exceptione){}
if(stm.........
if(cn............
}
3.可滾動的游標(biāo)
pageSize=20;
pageNo = 5;
cn = null
stmt = null;
rs = null;
try
{
sqlserver:sql = "select* from articles";
DataSource ds = new InitialContext().lookup(jndiurl);
Connection cn = ds.getConnection();
//"select * from user where id=?"--->binary directive
PreparedStatement pstmt = cn.prepareSatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,...);
//根據(jù)上面這行代碼的異常SQLFeatureNotSupportedException,就可判斷驅(qū)動是否支持可滾動游標(biāo)
ResultSet rs = pstmt.executeQuery()
rs.absolute((pageNo-1)*pageSize)
int i=0;
while(rs.next() && i<10)
{
i++;
out.println(rs.getString(1));
}
}
cacth(){}
finnaly
{
if(rs!=null)try{rs.close();}catch(Exceptione){}
if(stm.........
if(cn............
}
8.用一條SQL語句查詢出每門課都大于80分的學(xué)生姓名
name ? kecheng ? fenshu
張三 ? ?語文 ? ? ?81
張三 ? ?數(shù)學(xué) ? ? ?75
李四 ? ?語文 ? ? ?76
李四 ? ?數(shù)學(xué) ? ? ?90
王五 ? ?語文 ? ? ?81
王五 ? ?數(shù)學(xué) ? ? ?100
王五 ? ?英語 ? ? ?90
準(zhǔn)備數(shù)據(jù)的sql代碼:
create table score(id int primary key auto_increment,namevarchar(20),subject varchar(20),score int);
insert into score values
(null,'張三','語文',81),
(null,'張三','數(shù)學(xué)',75),
(null,'李四','語文',76),
(null,'李四','數(shù)學(xué)',90),
(null,'王五','語文',81),
(null,'王五','數(shù)學(xué)',100),
(null,'王五 ','英語',90);
提示:當(dāng)百思不得其解時抓歼,請理想思維讥此,把小變成大做,把大變成小做谣妻,
答案:
A: select distinct name from score ?where ?name not in (selectdistinct name from score where score<=80)
B:select distince name t1 from score where 80< all (selectscore from score where name=t1);
9.所有部門之間的比賽組合
一個叫department的表萄喳,里面只有一個字段name,一共有4條紀(jì)錄,分別是a,b,c,d,對應(yīng)四個球?qū)μ0耄F(xiàn)在四個球?qū)M(jìn)行比賽取胎,用一條sql語句顯示所有可能的比賽組合.
答:select a.name,b.name
from team a, team b
where a.name < b.name
10.每個月份的發(fā)生額都比101科目多的科目
請用SQL語句實現(xiàn):從TestDB數(shù)據(jù)表中查詢出所有月份的發(fā)生額都比101科目相應(yīng)月份的發(fā)生額高的科目。請注意:TestDB中有很多科目湃窍,都有1-12月份的發(fā)生額闻蛀。
AccID:科目代碼,Occmonth:發(fā)生額月份您市,DebitOccur:發(fā)生額觉痛。
數(shù)據(jù)庫名:JcyAudit,數(shù)據(jù)集:Select * from TestDB
準(zhǔn)備數(shù)據(jù)的sql代碼:
drop table if exists TestDB;
create table TestDB(id int primary key auto_increment,AccIDvarchar(20), Occmonth date, DebitOccur bigint);
insert into TestDB values
(null,'101','1988-1-1',100),
(null,'101','1988-2-1',110),
(null,'101','1988-3-1',120),
(null,'101','1988-4-1',100),
(null,'101','1988-5-1',100),
(null,'101','1988-6-1',100),
(null,'101','1988-7-1',100),
(null,'101','1988-8-1',100);
--復(fù)制上面的數(shù)據(jù)茵休,故意把第一個月份的發(fā)生額數(shù)字改小一點
insert into TestDB values
(null,'102','1988-1-1',90),
(null,'102','1988-2-1',110),
(null,'102','1988-3-1',120),
(null,'102','1988-4-1',100),
(null,'102','1988-5-1',100),
(null,'102','1988-6-1',100),
(null,'102','1988-7-1',100),
(null,'102','1988-8-1',100);
--復(fù)制最上面的數(shù)據(jù)薪棒,故意把所有發(fā)生額數(shù)字改大一點
insert into TestDB values
(null,'103','1988-1-1',150),
(null,'103','1988-2-1',160),
(null,'103','1988-3-1',180),
(null,'103','1988-4-1',120),
(null,'103','1988-5-1',120),
(null,'103','1988-6-1',120),
(null,'103','1988-7-1',120),
(null,'103','1988-8-1',120);
--復(fù)制最上面的數(shù)據(jù),故意把所有發(fā)生額數(shù)字改大一點
insert into TestDB values
(null,'104','1988-1-1',130),
(null,'104','1988-2-1',130),
(null,'104','1988-3-1',140),
(null,'104','1988-4-1',150),
(null,'104','1988-5-1',160),
(null,'104','1988-6-1',170),
(null,'104','1988-7-1',180),
(null,'104','1988-8-1',140);
--復(fù)制最上面的數(shù)據(jù)榕莺,故意把第二個月份的發(fā)生額數(shù)字改小一點
insert into TestDB values
(null,'105','1988-1-1',100),
(null,'105','1988-2-1',80),
(null,'105','1988-3-1',120),
(null,'105','1988-4-1',100),
(null,'105','1988-5-1',100),
(null,'105','1988-6-1',100),
(null,'105','1988-7-1',100),
(null,'105','1988-8-1',100);
答案:
select distinct AccID from TestDB
where AccID not in
(selectTestDB.AccIDfrom TestDB,
(select * from TestDB where AccID='101') asdb101
whereTestDB.Occmonth=db101.Occmonth and TestDB.DebitOccur<=db101.DebitOccur
);
11.統(tǒng)計每年每月的信息
year ?monthamount
1991 ? 1 ? ? 1.1
1991 ? 2 ? ? 1.2
1991 ? 3 ? ? 1.3
1991 ? 4 ? ? 1.4
1992 ? 1 ? ? 2.1
1992 ? 2 ? ? 2.2
1992 ? 3 ? ? 2.3
1992 ? 4 ? ? 2.4
查成這樣一個結(jié)果
year m1 ?m2 ?m3 ?m4
1991 1.1 1.2 1.3 1.4
1992 2.1 2.2 2.3 2.4
提示:這個與工資條非常類似俐芯,與學(xué)生的科目成績也很相似。
準(zhǔn)備sql語句:
drop table if existssales;
create table sales(idint auto_increment primary key,year varchar(10), month varchar(10), amountfloat(2,1));
insert into salesvalues
(null,'1991','1',1.1),
(null,'1991','2',1.2),
(null,'1991','3',1.3),
(null,'1991','4',1.4),
(null,'1992','1',2.1),
(null,'1992','2',2.2),
(null,'1992','3',2.3),
(null,'1992','4',2.4);
答案一钉鸯、
select sales.year ,
(select t.amount fromsales t where t.month='1' and t.year= sales.year) '1',
(select t.amount fromsales t where t.month='1' and t.year= sales.year) '2',
(select t.amount fromsales t where t.month='1' and t.year= sales.year) '3',
(select t.amount fromsales t where t.month='1' and t.year= sales.year) as '4'
from salesgroup by year;
12.顯示文章標(biāo)題吧史,發(fā)帖人、最后回復(fù)時間
表:id,title,postuser,postdate,parentid
準(zhǔn)備sql語句:
drop table if exists articles;
create table articles(id int auto_increment primary key,titlevarchar(50), postuser varchar(10), postdate datetime,parentid int referencesarticles(id));
insert into articles values
(null,'第一條','張三','1998-10-10 12:32:32',null),
(null,'第二條','張三','1998-10-10 12:34:32',null),
(null,'第一條回復(fù)1','李四','1998-10-10 12:35:32',1),
(null,'第二條回復(fù)1','李四','1998-10-10 12:36:32',2),
(null,'第一條回復(fù)2','王五','1998-10-10 12:37:32',1),
(null,'第一條回復(fù)3','李四','1998-10-10 12:38:32',1),
(null,'第二條回復(fù)2','李四','1998-10-10 12:39:32',2),
(null,'第一條回復(fù)4','王五','1998-10-10 12:39:40',1);
答案:
select a.title,a.postuser,
(selectmax(postdate) from articles where parentid=a.id) reply
from articles a where a.parentid is null;
注釋:子查詢可以用在選擇列中唠雕,也可用于where的比較條件中贸营,還可以用于from從句中。
13.刪除除了id號不同,其他都相同的學(xué)生冗余信息
2.學(xué)生表如下:
id號 ? 學(xué)號 ? 姓名課程編號課程名稱分?jǐn)?shù)
1 ? ? ? ?2005001 ?張三 0001 ? ? 數(shù)學(xué) ? ?69
2 ? ? ? ?2005002 ?李四 0001 ? ? 數(shù)學(xué) ? ?89
3 ? ? ? ?2005001 ?張三 0001 ? ? 數(shù)學(xué) ? ?69
A: delete from tablename where id號 not in(select min(id號) from tablename group by學(xué)號,姓名,課程編號,課程名稱,分?jǐn)?shù))
實驗:
create table student2(id int auto_increment primary key,codevarchar(20),name varchar(20));
insert into student2 values(null,'2005001','張三'),(null,'2005002','李四'),(null,'2005001','張三');
//如下語句岩睁,mysql報告錯誤钞脂,可能刪除依賴后面統(tǒng)計語句,而刪除又導(dǎo)致統(tǒng)計語句結(jié)果不一致捕儒。
delete from student2 where id not in(select min(id) fromstudent2 group by name);
//但是冰啃,如下語句沒有問題:
select *from student2where id not in(select min(id) from student2 group by name);
//于是,我想先把分組的結(jié)果做成虛表,然后從虛表中選出結(jié)果阎毅,最后再將結(jié)果作為刪除的條件數(shù)據(jù)焚刚。
delete from student2 where id not in(select mid from (selectmin(id) mid
from student2 group by name) as t);
或者:
delete from student2 where id not in(select min(id) from (select* from s
tudent2) as t group by t.name);
14.航空網(wǎng)的幾個航班查詢題:
表結(jié)構(gòu)如下:
flight{flightID,StartCityID ,endCityID,StartTime}
city{cityID, CityName)
實驗環(huán)境:
create table city(cityID int auto_increment primary key,cityNamevarchar(20));
create table flight (flightID int auto_increment primary key,
StartCityID intreferences city(cityID),
endCityID ?int references city(cityID),
StartTimetimestamp);
//航班本來應(yīng)該沒有日期部分才好,但是下面的題目當(dāng)中涉及到了日期
insert into city values(null,'北京'),(null,'上海'),(null,'廣州');
insert into flight values
(null,1,2,'9:37:23'),(null,1,3,'9:37:23'),(null,1,2,'10:37:23'),(null,2,3,'10:37:23');
1净薛、查詢起飛城市是北京的所有航班,按到達(dá)城市的名字排序
參與運(yùn)算的列是我起碼能夠顯示出來的那些列蒲拉,但最終我不一定把它們顯示出來肃拜。各個表組合出來的中間結(jié)果字段中必須包含所有運(yùn)算的字段。
select ?* from flight f,city c
where f.endcityid =c.cityid and startcityid =
(select c1.cityidfrom city c1 where c1.cityname = "北京")
order by c.citynameasc;
mysql> select flight.flightid,'北京' startcity, e.cityname from flight,city e wh
ere flight.endcityid=e.cityid and flight.startcityid=(selectcityid from city wh
ere cityname='北京');
mysql> select flight.flightid,s.cityname,e.cityname fromflight,city s,city e wh
ere flight.startcityid=s.cityid and s.cityname='北京' andflight.endCityId=e.cit
yID order by e.cityName desc;
2雌团、查詢北京到上海的所有航班紀(jì)錄(起飛城市燃领,到達(dá)城市,起飛時間锦援,航班號)
select c1.CityName,c2.CityName,f.StartTime,f.flightID
from city c1,city c2,flight f
where f.StartCityID=c1.cityID
and f.endCityID=c2.cityID
and c1.cityName='北京'
and c2.cityName='上海'
3猛蔽、查詢具體某一天(2005-5-8)的北京到上海的的航班次數(shù)
select count(*) from
(select c1.CityName,c2.CityName,f.StartTime,f.flightID
from city c1,city c2,flight f
where f.StartCityID=c1.cityID
and f.endCityID=c2.cityID
and c1.cityName='北京'
and c2.cityName='上海'
and 查幫助獲得的某個日期處理函數(shù)(startTime) like '2005-5-8%'
mysql中提取日期部分進(jìn)行比較的示例代碼如下:
select * from flight wheredate_format(starttime,'%Y-%m-%d')='1998-01-02'
15.查出比經(jīng)理薪水還高的員工信息:
Drop table if not exists employees;
create table employees(id int primary key auto_increment,namevarchar(50)
,salary int,managerid intreferences employees(id));
insert into employees values (null,' lhm',10000,null), (null,'zxx',15000,1
),(null,'flx',9000,1),(null,'tg',10000,2),(null,'wzg',10000,3);
Wzg大于flx,lhm大于zxx
解題思路:
根據(jù)sql語句的查詢特點,是逐行進(jìn)行運(yùn)算灵寺,不可能兩行同時參與運(yùn)算曼库。
涉及了員工薪水和經(jīng)理薪水,所有略板,一行記錄要同時包含兩個薪水毁枯,所有想到要把這個表自關(guān)聯(lián)組合一下。
首先要組合出一個包含有各個員工及該員工的經(jīng)理信息的長記錄叮称,譬如种玛,左半部分是員工,右半部分是經(jīng)理瓤檐。而迪卡爾積會組合出很多垃圾信息赂韵,先去除這些垃圾信息。
select e.* from employees e,employees m where e.managerid=m.idand e.sala
ry>m.salary;
16挠蛉、求出小于45歲的各個老師所帶的大于12歲的學(xué)生人數(shù)
數(shù)據(jù)庫中有3個表 teacher表祭示,student表蛋勺,tea_stu關(guān)系表涧团。
teacher 表 teaID name age
student 表 stuID name age
teacher_student表 teaID stuID
要求用一條sql查詢出這樣的結(jié)果
1.顯示的字段要有老師name, age每個老師所帶的學(xué)生人數(shù)
2 只列出老師age為40以下,學(xué)生age為12以上的記錄
預(yù)備知識:
1.sql語句是對每一條記錄依次處理急凰,條件為真則執(zhí)行動作(select,insert,delete,update)
2.只要是迪卡爾積讥电,就會產(chǎn)生“垃圾”信息蹂窖,所以,只要迪卡爾積了恩敌,我們首先就要想到清除“垃圾”信息
實驗準(zhǔn)備:
drop table if exists tea_stu;
drop table if exists teacher;
drop table if exists student;
create table teacher(teaID int primarykey,name varchar(50),age int);
create table student(stuID int primarykey,name varchar(50),age int);
create table tea_stu(teaID int referencesteacher(teaID),stuID int references student(stuID));
insertinto teacher values(1,'zxx',45), (2,'lhm',25) , (3,'wzg',26) , (4,'tg',27);
insertinto student values(1,'wy',11), (2,'dh',25) , (3,'ysq',26) , (4,'mxc',27);
insertinto tea_stu values(1,1), (1,2), (1,3);
insertinto tea_stu values(2,2), (2,3), (2,4);
insert into tea_stu values(3,3), (3,4), (3,1);
insertinto tea_stu values(4,4), (4,1), (4,2) , (4,3);
結(jié)果:2à3,3à2,4à3
解題思路:(真實面試答題時瞬测,也要寫出每個分析步驟,如果紙張不夠,就找別人要)
1要會統(tǒng)計分組信息月趟,統(tǒng)計信息放在中間表中:
selectteaid,count(*) from tea_stu group by teaid;
2接著其實應(yīng)該是篩除掉小于12歲的學(xué)生灯蝴,然后再進(jìn)行統(tǒng)計,中間表必須與student關(guān)聯(lián)才能得到12歲以下學(xué)生和把該學(xué)生記錄從中間表中剔除孝宗,代碼是:
selecttea_stu.teaid,count(*) total from student,tea_stu
wherestudent.stuid=tea_stu.stuid and student.age>12 group by tea_stu.teaid
3.接著把上面的結(jié)果做成虛表與teacher進(jìn)行關(guān)聯(lián)穷躁,并篩除大于45的老師
selectteacher.teaid,teacher.name,total from teacher ,(select tea_stu.tea
id,count(*)total from student,tea_stu where student.stuid=tea_stu.stuid and stu
dent.age>12group by tea_stu.teaid) as tea_stu2where teacher.teaid=tea_stu2.tea
idand teacher.age<45;
17.求出發(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
這條語句不行,因為max只有一列因妇,不能與其他列混淆问潭。
select authorid,count(*) total from articles
group by authorid having total=max(total)也不行。
18婚被、一個用戶表中有一個積分字段狡忙,假如數(shù)據(jù)庫中有100多萬個用戶,若要在每年第一天凌晨將積分清零址芯,你將考慮什么灾茁,你將想什么辦法解決?
alter table drop column score;
alter table add colunm score int;
可能會很快,但是需要試驗谷炸,試驗不能拿真實的環(huán)境來操刀北专,并且要注意,
這樣的操作時無法回滾的旬陡,在我的印象中逗余,只有inert update delete等DML語句才能回滾,
對于create table,drop table ,alter table等DDL語句是不能回滾季惩。
解決方案一录粱,update user set score=0;
解決方案二,假設(shè)上面的代碼要執(zhí)行好長時間画拾,超出我們的容忍范圍啥繁,那我就alter table user drop columnscore;alter table user add column score int。
下面代碼實現(xiàn)每年的那個凌晨時刻進(jìn)行清零青抛。
Runnable runnable =
new Runnable(){
public voidrun(){
clearDb();
schedule(this,newDate(new Date().getYear()+1,0,0));
}
};
schedule(runnable,
new Date(newDate().getYear()+1,0,1));
19旗闽、一個用戶具有多個角色,請查詢出該表中具有該用戶的所有角色的其他用戶蜜另。
select count(*) as num,tb.id
from
tb,
(select role from tbwhere id=xxx) as t1
where
tb.role = t1.role andtb.id != t1.id
group by tb.id
having
num = select count(role)from tb where id=xxx;
20. xxx公司的sql面試
TableEMPLOYEESStructure:
EMPLOYEE_IDNUMBER ? ? ? ?Primary Key,
FIRST_NAMEVARCHAR2(25),
LAST_NAMEVARCHAR2(25),
Salary number(8,2),
HiredDate DATE,
Departmentid number(2)
TableDepartmentsStructure:
Departmentid number(2)Primary Key,
DepartmentNameVARCHAR2(25).
(2)基于上述EMPLOYEES表寫出查詢:寫出雇用日期在今年的适室,或者工資在[1000,2000]之間的,或者員工姓名(last_name)以’Obama’打頭的所有員工举瑰,列出這些員工的全部個人信息捣辆。(4分)
select* from employees
whereYear(hiredDate) = Year(date())
or (salary between 1000 and 200)
or left(last_name,3)='abc';
(3) 基于上述EMPLOYEES表寫出查詢:查出部門平均工資大于1800元的部門的所有員工,列出這些員工的全部個人信息此迅。(4分)
mysql>select id,name,salary,deptid did from employee1 where (select avg(salary)
from employee1 where deptid = did) > 1800;
(4) 基于上述EMPLOYEES表寫出查詢:查出個人工資高于其所在部門平均工資的員工汽畴,列出這些員工的全部個人信息及該員工工資高出部門平均工資百分比旧巾。(5分)
selectemployee1.*,(employee1.salary-t.avgSalary)*100/employee1.salary
fromemployee1,
(select deptid,avg(salary) avgSalary fromemployee1 group by deptid) as t
whereemployee1.deptid = t.deptid and employee1.salary>t.avgSalary;
21、注冊Jdbc驅(qū)動程序的三種方式
22忍些、用JDBC如何調(diào)用存儲過程
代碼如下:
packagecom.huawei.interview.lym;
importjava.sql.CallableStatement;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.SQLException;
importjava.sql.Types;
publicclassJdbcTest {
/**
*@paramargs
*/
public static voidmain(String[] args) {
//TODOAuto-generated method stub
Connection cn =null;
CallableStatement cstmt =null;
try{
//這里最好不要這么干鲁猩,因為驅(qū)動名寫死在程序中了
Class.forName("com.mysql.jdbc.Driver");
//實際項目中,這里應(yīng)用DataSource數(shù)據(jù)罢坝,如果用框架廓握,
//這個數(shù)據(jù)源不需要我們編碼創(chuàng)建,我們只需Datasource ds =context.lookup()
//cn = ds.getConnection();
cn = DriverManager.getConnection("jdbc:mysql:///test","root","root");
cstmt = cn.prepareCall("{callinsert_Student(?,?,?)}");
cstmt.registerOutParameter(3,Types.INTEGER);
cstmt.setString(1,"wangwu");
cstmt.setInt(2, 25);
cstmt.execute();
//get第幾個嘁酿,不同的數(shù)據(jù)庫不一樣隙券,建議不寫
System.out.println(cstmt.getString(3));
}catch(Exception e) {
//TODOAuto-generated catchblock
e.printStackTrace();
}
finally
{
/*try{cstmt.close();}catch(Exceptione){}
try{cn.close();}catch(Exceptione){}*/
try{
if(cstmt !=null)
cstmt.close();
if(cn !=null)
cn.close();
}catch(SQLException e) {
//TODOAuto-generatedcatch block
e.printStackTrace();
}
}
}
23、JDBC中的PreparedStatement相比Statement的好處
答:一個sql命令發(fā)給服務(wù)器去執(zhí)行的步驟為:語法檢查痹仙,語義分析是尔,編譯成內(nèi)部指令殉了,緩存指令开仰,執(zhí)行指令等過程。
select * from student where id =3----緩存--àxxxxx二進(jìn)制命令
select * from student where id =3----直接取-àxxxxx二進(jìn)制命令
select * from student where id =4--- -à會怎么干薪铜?
如果當(dāng)初是select * from student where id =?--- -à又會怎么干众弓?
上面說的是性能提高
可以防止sql注入。
24. 寫一個用jdbc連接并訪問oracle數(shù)據(jù)的程序代碼
25隔箍、Class.forName的作用?為什么要用?
答:按參數(shù)中指定的字符串形式的類名去搜索并加載相應(yīng)的類谓娃,如果該類字節(jié)碼已經(jīng)被加載過,則返回代表該字節(jié)碼的Class實例對象蜒滩,否則滨达,按類加載器的委托機(jī)制去搜索和加載該類,如果所有的類加載器都無法加載到該類俯艰,則拋出ClassNotFoundException捡遍。加載完這個Class字節(jié)碼后,接著就可以使用Class字節(jié)碼的newInstance方法去創(chuàng)建該類的實例對象了竹握。
有時候画株,我們程序中所有使用的具體類名在設(shè)計時(即開發(fā)時)無法確定怒竿,只有程序運(yùn)行時才能確定牢屋,這時候就需要使用Class.forName去動態(tài)加載該類,這個類名通常是在配置文件中配置的聘殖,例如芹关,spring的ioc中每次依賴注入的具體類就是這樣配置的续挟,jdbc的驅(qū)動類名通常也是通過配置文件來配置的,以便在產(chǎn)品交付使用后不用修改源程序就可以更換驅(qū)動類名侥衬。
26庸推、大數(shù)據(jù)量下的分頁解決方法常侦。
答:最好的辦法是利用sql語句進(jìn)行分頁,這樣每次查詢出的結(jié)果集中就只包含某頁的數(shù)據(jù)內(nèi)容贬媒。再sql語句無法實現(xiàn)分頁的情況下聋亡,可以考慮對大的結(jié)果集通過游標(biāo)定位方式來獲取某頁的數(shù)據(jù)。
sql語句分頁际乘,不同的數(shù)據(jù)庫下的分頁方案各不一樣坡倔,下面是主流的三種數(shù)據(jù)庫的分頁sql:
sql server:
String sql =
"select top" + pageSize + " * from students where id not in" +
"(select top "+ pageSize * (pageNumber-1) + " id from students order by id)" +
"order by id";
mysql:
String sql =
"select * fromstudents order by id limit " + pageSize*(pageNumber-1) + "," +pageSize;
oracle:
String sql =
"select * from " +
(select *,rownum rid from (select * fromstudents order by postime desc) where rid<=" + pagesize*pagenumber +") as t" +
"where t>" +pageSize*(pageNumber-1);
27、用 JDBC查詢學(xué)生成績單,把主要代碼寫出來(考試概率極大).
Connection cn = null;
PreparedStatement pstmt =null;
Resultset rs = null;
try
{
Class.forname(driveClassName);
cn = ?DriverManager.getConnection(url,username,password);
pstmt =cn.prepareStatement(“select ?score.* fromscore ,student “ +
“wherescore.stuId = student.id and student.name = ?”);
pstmt.setString(1,studentName);
Resultset rs =pstmt.executeQuery();
while(rs.next())
{
system.out.println(rs.getInt(“subject”) ?+ ?“ ? ?” + rs.getFloat(“score”) );
}
}catch(Exception e){e.printStackTrace();}
finally
{
if(rs != null) try{rs.close() }catch(exception e){}
if(pstmt != null)try{pstmt.close()}catch(exception e){}
if(cn != null) try{cn.close() }catch(exception e){}
}
28脖含、這段代碼有什么不足之處?
try {
Connection conn = ...;
Statement stmt = ...;
ResultSet rs =stmt.executeQuery("select * from table1");
while(rs.next()) {
}
} catch(Exception ex) {
}
答:沒有finally語句來關(guān)閉各個對象罪塔,另外,使用finally之后养葵,要把變量的定義放在try語句塊的外面征堪,以便在try語句塊之外的finally塊中仍可以訪問這些變量。
29关拒、說出數(shù)據(jù)連接池的工作機(jī)制是什么?
J2EE服務(wù)器啟動時會建立一定數(shù)量的池連接佃蚜,并一直維持不少于此數(shù)目的池連接∽虐恚客戶端程序需要連接時谐算,池驅(qū)動程序會返回一個未使用的池連接并將其表記為忙。如果當(dāng)前沒有空閑連接归露,池驅(qū)動程序就新建一定數(shù)量的連接洲脂,新建連接的數(shù)量有配置參數(shù)決定。當(dāng)使用的池連接調(diào)用完成后剧包,池驅(qū)動程序?qū)⒋诉B接表記為空閑恐锦,其他調(diào)用就可以使用這個連接。
實現(xiàn)方式疆液,返回的Connection是原始Connection的代理一铅,代理Connection的close方法不是真正關(guān)連接,而是把它代理的Connection對象還回到連接池中枚粘。
30馅闽、為什么要用 ORM? 和 JDBC有何不一樣?
orm是一種思想,就是把object轉(zhuǎn)變成數(shù)據(jù)庫中的記錄馍迄,或者把數(shù)據(jù)庫中的記錄轉(zhuǎn)變成objecdt福也,我們可以用jdbc來實現(xiàn)這種思想,其實攀圈,如果我們的項目是嚴(yán)格按照oop方式編寫的話暴凑,我們的jdbc程序不管是有意還是無意,就已經(jīng)在實現(xiàn)orm的工作了赘来。
現(xiàn)在有許多orm工具现喳,它們底層調(diào)用jdbc來實現(xiàn)了orm工作凯傲,我們直接使用這些工具,就省去了直接使用jdbc的繁瑣細(xì)節(jié)嗦篱,提高了開發(fā)效率冰单,現(xiàn)在用的較多的orm工具是hibernate。也聽說一些其他orm工具灸促,如toplink,ojb等诫欠。
六. XML部分
1、xml有哪些解析技術(shù)?區(qū)別是什么?
答:有DOM,SAX,STAX等
DOM:處理大型文件時其性能下降的非常厲害浴栽。這個問題是由DOM的樹結(jié)構(gòu)所造成的荒叼,這種結(jié)構(gòu)占用的內(nèi)存較多,而且DOM必須在解析文件之前把整個文檔裝入內(nèi)存,適合對XML的隨機(jī)訪問SAX:不現(xiàn)于DOM,SAX是事件驅(qū)動型的XML解析方式典鸡。它順序讀取XML文件被廓,不需要一次全部裝載整個文件。當(dāng)遇到像文件開頭萝玷,文檔結(jié)束嫁乘,或者標(biāo)簽開頭與標(biāo)簽結(jié)束時,它會觸發(fā)一個事件间护,用戶通過在其回調(diào)事件中寫入處理代碼來處理XML文件亦渗,適合對XML的順序訪問
STAX:Streaming API for XML (StAX)
講解這些區(qū)別是不需要特別去比較挖诸,就像說傳智播客與其他培訓(xùn)機(jī)構(gòu)的區(qū)別時汁尺,我們只需說清楚傳智播客有什么特點和優(yōu)點就行了,這就已經(jīng)間接回答了彼此的區(qū)別多律。
2痴突、你在項目中用到了xml技術(shù)的哪些方面?如何實現(xiàn)的?
答:用到了數(shù)據(jù)存貯,信息配置兩方面狼荞。在做數(shù)據(jù)交換平臺時辽装,將不能數(shù)據(jù)源的數(shù)據(jù)組裝成XML文件,然后將XML文件壓縮打包加密后通過網(wǎng)絡(luò)傳送給接收者相味,接收解密與解壓縮后再同XML文件中還原相關(guān)信息進(jìn)行處理拾积。在做軟件配置時,利用XML可以很方便的進(jìn)行丰涉,軟件的各種配置參數(shù)都存貯在XML文件中旨袒。
3跨扮、用jdom解析xml文件時如何解決中文問題?如何解析?
答:看如下代碼,用編碼方式加以解決
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(newjavax.xml.transform.dom.DOMSource(doc),
new
javax.xml.transform.stream.StreamResult(outFile));
}
catch (Exception e)
{
System.out.println (e.getMessage());
}
}
}
4、編程用JAVA解析XML的方式.
答:用SAX方式解析XML,XML文件如下:
王小明
信息學(xué)院
6258113
男,1955年生,博士兴想,95年調(diào)入海南大學(xué)
事件回調(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:
剖析XML文件people.xml
<%@ 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();教師信息表
姓名 +
(String)hashTable.get(new String(name)) +);
學(xué)院 +
(String)hashTable.get(newString(college))+);
電話 +
(String)hashTable.get(new String(telephone)) +);
備注 +
(String)hashTable.get(new String(notes)) +);
out.println();
%>
5、XML文檔定義有幾種形式荧降?它們之間有何本質(zhì)區(qū)別?解析XML文檔有哪幾種方式冠骄?
a: 兩種形式 dtdschema,b:本質(zhì)區(qū)別:schema本身是xml的加袋,可以被XML解析器解析(這也是從DTD上發(fā)展schema的根本目的)凛辣,c:有DOM,SAX,STAX等
DOM:處理大型文件時其性能下降的非常厲害。這個問題是由DOM的樹結(jié)構(gòu)所造成的职烧,這種結(jié)構(gòu)占用的內(nèi)存較多蟀给,而且DOM必須在解析文件之前把整個文檔裝入內(nèi)存,適合對XML的隨機(jī)訪問
SAX:不現(xiàn)于DOM,SAX是事件驅(qū)動型的XML解析方式。它順序讀取XML文件阳堕,不需要一次全部裝載整個文件跋理。當(dāng)遇到像文件開頭,文檔結(jié)束恬总,或者標(biāo)簽開頭與標(biāo)簽結(jié)束時前普,它會觸發(fā)一個事件,用戶通過在其回調(diào)事件中寫入處理代碼來處理XML文件壹堰,適合對XML的順序訪問
STAX:Streaming API forXML (StAX)
七.流行的框架與新技術(shù)
1拭卿、談?wù)勀銓truts的理解。
答:
1. struts是一個按MVC模式設(shè)計的Web層框架贱纠,其實它就是一個大大的servlet峻厚,這個Servlet名為ActionServlet,或是ActionServlet的子類谆焊。我們可以在web.xml文件中將符合某種特征的所有請求交給這個Servlet處理惠桃,這個Servlet再參照一個配置文件(通常為/WEB-INF/struts-config.xml)將各個請求分別分配給不同的action去處理。
一個擴(kuò)展知識點:struts的配置文件可以有多個辖试,可以按模塊配置各自的配置文件辜王,這樣可以防止配置文件的過度膨脹;
2.ActionServlet把請求交給action去處理之前罐孝,會將請求參數(shù)封裝成一個formbean對象(就是一個java類呐馆,這個類中的每個屬性對應(yīng)一個請求參數(shù)),封裝成一個什么樣的formbean對象呢莲兢?看配置文件汹来。
3.要說明的是, ActionServlet把formbean對象傳遞給action的execute方法之前改艇,可能會調(diào)用formbean的validate方法進(jìn)行校驗收班,只有校驗通過后才將這個formbean對象傳遞給action的execute方法,否則遣耍,它將返回一個錯誤頁面闺阱,這個錯誤頁面由input屬性指定,(看配置文件)作者為什么將這里命名為input屬性舵变,而不是error屬性酣溃,我們后面結(jié)合實際的運(yùn)行效果進(jìn)行分析瘦穆。
4.action執(zhí)行完后要返回顯示的結(jié)果視圖,這個結(jié)果視圖是用一個ActionForward對象來表示的赊豌,actionforward對象通過struts-config.xml配置文件中的配置關(guān)聯(lián)到某個jsp頁面扛或,因為程序中使用的是在struts-config.xml配置文件為jsp頁面設(shè)置的邏輯名,這樣可以實現(xiàn)action程序代碼與返回的jsp頁面名稱的解耦碘饼。
你對struts可能還有自己的應(yīng)用方面的經(jīng)驗熙兔,那也要一并說出來。
2艾恼、談?wù)勀銓ibernate的理解住涉。
答:
1. 面向?qū)ο笤O(shè)計的軟件內(nèi)部運(yùn)行過程可以理解成就是在不斷創(chuàng)建各種新對象、建立對象之間的關(guān)系钠绍,調(diào)用對象的方法來改變各個對象的狀態(tài)和對象消亡的過程舆声,不管程序運(yùn)行的過程和操作怎么樣,本質(zhì)上都是要得到一個結(jié)果柳爽,程序上一個時刻和下一個時刻的運(yùn)行結(jié)果的差異就表現(xiàn)在內(nèi)存中的對象狀態(tài)發(fā)生了變化媳握。
2.為了在關(guān)機(jī)和內(nèi)存空間不夠的狀況下,保持程序的運(yùn)行狀態(tài)磷脯,需要將內(nèi)存中的對象狀態(tài)保存到持久化設(shè)備和從持久化設(shè)備中恢復(fù)出對象的狀態(tài)蛾找,通常都是保存到關(guān)系數(shù)據(jù)庫來保存大量對象信息。從Java程序的運(yùn)行功能上來講赵誓,保存對象狀態(tài)的功能相比系統(tǒng)運(yùn)行的其他功能來說打毛,應(yīng)該是一個很不起眼的附屬功能,java采用jdbc來實現(xiàn)這個功能架曹,這個不起眼的功能卻要編寫大量的代碼隘冲,而做的事情僅僅是保存對象和恢復(fù)對象闹瞧,并且那些大量的jdbc代碼并沒有什么技術(shù)含量绑雄,基本上是采用一套例行公事的標(biāo)準(zhǔn)代碼模板來編寫,是一種苦活和重復(fù)性的工作奥邮。
3.通過數(shù)據(jù)庫保存java程序運(yùn)行時產(chǎn)生的對象和恢復(fù)對象万牺,其實就是實現(xiàn)了java對象與關(guān)系數(shù)據(jù)庫記錄的映射關(guān)系,稱為ORM(即Object RelationMapping)洽腺,人們可以通過封裝JDBC代碼來實現(xiàn)了這種功能脚粟,封裝出來的產(chǎn)品稱之為ORM框架,Hibernate就是其中的一種流行ORM框架蘸朋。使用Hibernate框架,不用寫JDBC代碼,僅僅是調(diào)用一個save方法诸老,就可以將對象保存到關(guān)系數(shù)據(jù)庫中,僅僅是調(diào)用一個get方法噪沙,就可以從數(shù)據(jù)庫中加載出一個對象。
4.使用Hibernate的基本流程是:配置Configuration對象吐根、產(chǎn)生SessionFactory正歼、創(chuàng)建session對象,啟動事務(wù)拷橘,完成CRUD操作局义,提交事務(wù),關(guān)閉session冗疮。
5.使用Hibernate時萄唇,先要配置hibernate.cfg.xml文件,其中配置數(shù)據(jù)庫連接信息和方言等术幔,還要為每個實體配置相應(yīng)的hbm.xml文件穷绵,hibernate.cfg.xml文件中需要登記每個hbm.xml文件。
6.在應(yīng)用Hibernate時特愿,重點要了解Session的緩存原理仲墨,級聯(lián),延遲加載和hql查詢揍障。
3目养、AOP的作用。
4毒嫡、你對Spring的理解癌蚁。
1.Spring實現(xiàn)了工廠模式的工廠類(在這里有必要解釋清楚什么是工廠模式),這個類名為BeanFactory(實際上是一個接口)兜畸,在程序中通常BeanFactory的子類ApplicationContext努释。Spring相當(dāng)于一個大的工廠類,在其配置文件中通過元素配置用于創(chuàng)建實例對象的類名和實例對象的屬性咬摇。
2. Spring提供了對IOC良好支持伐蒂,IOC是一種編程思想,是一種架構(gòu)藝術(shù)肛鹏,利用這種思想可以很好地實現(xiàn)模塊之間的解耦逸邦。IOC也稱為DI(Depency Injection),什么叫依賴注入呢在扰?
譬如缕减,Class Programmer
{
Computer computer =null;
public void code()
{
//Computercomputer = new IBMComputer();
//Computercomputer = beanfacotry.getComputer();
computer.write();
}
public voidsetComputer(Computer computer)
{
this.computer= computer;
}
}
另外兩種方式都由依賴,第一個直接依賴于目標(biāo)類芒珠,第二個把依賴轉(zhuǎn)移到工廠上桥狡,第三個徹底與目標(biāo)和工廠解耦了。在spring的配置文件中配置片段如下:
3. Spring提供了對AOP技術(shù)的良好封裝, AOP稱為面向切面編程裹芝,就是系統(tǒng)中有很多各不相干的類的方法呈宇,在這些眾多方法中要加入某種系統(tǒng)功能的代碼,例如局雄,加入日志甥啄,加入權(quán)限判斷,加入異常處理炬搭,這種應(yīng)用稱為AOP蜈漓。實現(xiàn)AOP功能采用的是代理技術(shù),客戶端程序不再調(diào)用目標(biāo)宫盔,而調(diào)用代理類融虽,代理類與目標(biāo)類對外具有相同的方法聲明,有兩種方式可以實現(xiàn)相同的方法聲明灼芭,一是實現(xiàn)相同的接口有额,二是作為目標(biāo)的子類在,JDK中采用Proxy類產(chǎn)生動態(tài)代理的方式為某個接口生成實現(xiàn)類彼绷,如果要為某個類生成子類巍佑,則可以用CGLI B。在生成的代理類的方法中加入系統(tǒng)功能和調(diào)用目標(biāo)類的相應(yīng)方法寄悯,系統(tǒng)功能的代理以Advice對象進(jìn)行提供萤衰,顯然要創(chuàng)建出代理對象,至少需要目標(biāo)類和Advice類猜旬。spring提供了這種支持脆栋,只需要在spring配置文件中配置這兩個元素即可實現(xiàn)代理和aop功能,例如洒擦,
5椿争、談?wù)凷truts中的Action servlet。
6熟嫩、Struts優(yōu)缺點
優(yōu)點:
1.實現(xiàn)MVC模式秦踪,結(jié)構(gòu)清晰,使開發(fā)者只關(guān)注業(yè)務(wù)邏輯的實現(xiàn).
2.有豐富的tag可以用 ,Struts的標(biāo)記庫(Taglib),如能靈活動用邦危,則能大大提高開發(fā)效率
3. 頁面導(dǎo)航
使系統(tǒng)的脈絡(luò)更加清晰洋侨。通過一個配置文件,即可把握整個系統(tǒng)各部分之間的聯(lián)系倦蚪,這對于后期的維護(hù)有著莫大的好處。尤其是當(dāng)另一批開發(fā)者接手這個項目時边苹,這種優(yōu)勢體現(xiàn)得更加明顯陵且。
4. 提供Exception處理機(jī)制 .
5. 數(shù)據(jù)庫鏈接池管理
6. 支持I18N
缺點
一、 ? 轉(zhuǎn)到展示層時,需要配置forward慕购,如果有十個展示層的jsp聊疲,需要配置十次struts,而且還不包括有時候目錄沪悲、文件變更影所,需要重新修改forward西壮,注意,每次修改配置之后,要求重新部署整個項目议忽,而tomcate這樣的服務(wù)器,還必須重新啟動服務(wù)器
二江咳、 ? 二峭火、 Struts的Action必需是thread-safe方式,它僅僅允許一個實例去處理所有的請求烤送。所以action用到的所有的資源都必需統(tǒng)一同步寒随,這個就引起了線程安全的問題。
三帮坚、 ? ?測試不方便. Struts的每個Action都同Web層耦合在一起妻往,這樣它的測試依賴于Web容器,單元測試也很難實現(xiàn)试和。不過有一個Junit的擴(kuò)展工具Struts TestCase可以實現(xiàn)它的單元測試蒲讯。
四、 ? ?類型的轉(zhuǎn)換. Struts的FormBean把所有的數(shù)據(jù)都作為String類型灰署,它可以使用工具Commons-Beanutils進(jìn)行類型轉(zhuǎn)化判帮。但它的轉(zhuǎn)化都是在Class級別,而且轉(zhuǎn)化的類型是不可配置的溉箕。類型轉(zhuǎn)化時的錯誤信息返回給用戶也是非常困難的晦墙。
五、 ? 對Servlet的依賴性過強(qiáng). Struts處理Action時必需要依賴ServletRequest和ServletResponse肴茄,所有它擺脫不了Servlet容器晌畅。
六、 ? ?前端表達(dá)式語言方面.Struts集成了JSTL寡痰,所以它主要使用JSTL的表達(dá)式語言來獲取數(shù)據(jù)抗楔。可是JSTL的表達(dá)式語言在Collection和索引屬性方面處理顯得很弱拦坠。
七连躏、 ? ?對Action執(zhí)行的控制困難. Struts創(chuàng)建一個Action,如果想控制它的執(zhí)行順序?qū)浅@щy贞滨。甚至你要重新去寫Servlet來實現(xiàn)你的這個功能需求入热。
八、 ? ?對Action執(zhí)行前和后的處理. Struts處理Action的時候是基于class的hierarchies,很難在action處理前和后進(jìn)行操作勺良。
九绰播、 ? ?對事件支持不夠.在struts中,實際是一個表單Form對應(yīng)一個Action類(或DispatchAction)尚困,換一句話說:在Struts中實際是一個表單只能對應(yīng)一個事件蠢箩,struts這種事件方式稱為application event,application event和component event相比是一種粗粒度的事件
7事甜、STRUTS的應(yīng)用(如STRUTS架構(gòu))
Struts是采用Java Servlet/JavaServer Pages技術(shù)谬泌,開發(fā)Web應(yīng)用程序的開放源碼的framework。采用Struts能開發(fā)出基于MVC(Model-View-Controller)設(shè)計模式的應(yīng)用構(gòu)架讳侨。 Struts有如下的主要功能:一.包含一個controller servlet呵萨,能將用戶的請求發(fā)送到相應(yīng)的Action對象。二.JSP自由tag庫跨跨,并且在controller servlet中提供關(guān)聯(lián)支持潮峦,幫助開發(fā)員創(chuàng)建交互式表單應(yīng)用。三.提供了一系列實用對象:XML處理勇婴、通過Java reflection APIs自動處理JavaBeans屬性忱嘹、國際化的提示和消息。
8耕渴、說說struts1與struts2的區(qū)別拘悦。
1.都是MVC的WEB框架,
2 struts1的老牌框架,應(yīng)用很廣泛橱脸,有很好的群眾基礎(chǔ)础米,使用它開發(fā)風(fēng)險很小,成本更低添诉!struts2雖然基于這個框架屁桑,但是應(yīng)用群眾并多,相對不成熟栏赴,未知的風(fēng)險和變化很多蘑斧,開發(fā)人員相對不好招,使用它開發(fā)項目的風(fēng)險系數(shù)更大须眷,用人成本更高竖瘾!
3.struts2畢竟是站在前輩的基礎(chǔ)設(shè)計出來,它會改善和完善struts1中的一些缺陷花颗,struts1中一些懸而未決問題在struts2得到了解決捕传。
4.struts1的前端控制器是一個Servlet,名稱為ActionServlet捎稚,struts2的前端控制器是一個filter乐横,在struts2.0中叫FilterDispatcher求橄,在struts2.1中叫StrutsPrepareAndExecuteFilter今野。
5.struts1的action需要繼承Action類葡公,struts2的action可以不繼承任何類;struts1對同一個路徑的所有請求共享一個Action實例条霜,struts2對同一個路徑的每個請求分別使用一個獨立Action實例對象催什,所有對于struts2的Action不用考慮線程安全問題。
6.在struts1中使用formbean封裝請求參數(shù)宰睡,在struts2中直接使用action的屬性來封裝請求參數(shù)蒲凶。
7.struts1中的多個業(yè)務(wù)方法放在一個Action中時(即繼承DispatchAction時),要么都校驗拆内,要么都不校驗;對于struts2,可以指定只對某個方法進(jìn)行校驗贴膘,當(dāng)一個Action繼承了ActionSupport且在這個類中只編寫了validateXxx()方法拼弃,那么則只對Xxx()方法進(jìn)行校驗。
(一個請求來了的執(zhí)行流程進(jìn)行分析抹沪,struts2是自動支持分模塊開發(fā)刻肄,并可以不同模塊設(shè)置不同的url前綴,這是通過package的namespace來實現(xiàn)的融欧;struts2是支持多種類型的視圖敏弃;struts2的視圖地址可以是動態(tài)的,即視圖的名稱是支持變量方式的噪馏,舉例麦到,論壇發(fā)帖失敗后回來還要傳遞boardid。視圖內(nèi)容顯示方面:它的標(biāo)簽用ognl欠肾,要el強(qiáng)大很多瓶颠,在國際化方面支持分模塊管理,兩個模塊用到同樣的key董济,對應(yīng)不同的消息步清;)
與Struts1不同,Struts2對用戶的每一次請求都會創(chuàng)建一個Action虏肾,所以Struts2中的Action是線程安全的廓啊。
給我印象最深刻的是:struts配置文件中的redirect視圖的url不能接受參數(shù),而struts2配置文件中的redirect視圖可以接受參數(shù)封豪。
9谴轮、hibernate中的update()和saveOrUpdate()的區(qū)別,session的load()和get()的區(qū)別吹埠。
10第步、簡述 Hibernate和 JDBC的優(yōu)缺點?如何書寫一個 one to many配置文件.
11疮装、iBatis與Hibernate有什么不同?
相同點:屏蔽jdbc api的底層訪問細(xì)節(jié),使用我們不用與jdbc api打交道粘都,就可以訪問數(shù)據(jù)廓推。
jdbc api編程流程固定,還將sql語句與java代碼混雜在了一起翩隧,經(jīng)常需要拼湊sql語句樊展,細(xì)節(jié)很繁瑣。
ibatis的好處:屏蔽jdbc api的底層訪問細(xì)節(jié)堆生;將sql語句與java代碼進(jìn)行分離;提供了將結(jié)果集自動封裝稱為實體對象和對象的集合的功能专缠,queryForList返回對象集合,用queryForObject返回單個對象淑仆;提供了自動將實體對象的屬性傳遞給sql語句的參數(shù)涝婉。
Hibernate是一個全自動的orm映射工具,它可以自動生成sql語句,ibatis需要我們自己在xml配置文件中寫sql語句蔗怠,hibernate要比ibatis功能負(fù)責(zé)和強(qiáng)大很多墩弯。因為hibernate自動生成sql語句,我們無法控制該語句蟀淮,我們就無法去寫特定的高效率的sql最住。對于一些不太復(fù)雜的sql查詢,hibernate可以很好幫我們完成怠惶,但是涨缚,對于特別復(fù)雜的查詢,hibernate就很難適應(yīng)了策治,這時候用ibatis就是不錯的選擇脓魏,因為ibatis還是由我們自己寫sql語句。
12通惫、寫Hibernate的一對多和多對一雙向關(guān)聯(lián)的orm配置?
9茂翔、hibernate的inverse屬性的作用?
解決方案一,按照Object[]數(shù)據(jù)取出數(shù)據(jù)履腋,然后自己組bean
解決方案二珊燎,對每個表的bean寫構(gòu)造函數(shù),比如表一要查出field1,field2兩個字段遵湖,那么有一個構(gòu)造函數(shù)就是Bean(type1filed1,type2
field2) 悔政,然后在hql里面就可以直接生成這個bean了。
13延旧、在DAO中如何體現(xiàn)DAO設(shè)計模式?
解決方案一谋国,按照Object[]數(shù)據(jù)取出數(shù)據(jù),然后自己組bean
解決方案二迁沫,對每個表的bean寫構(gòu)造函數(shù)芦瘾,比如表一要查出field1,field2兩個字段捌蚊,那么有一個構(gòu)造函數(shù)就是Bean(type1filed1,type2
field2) ,然后在hql里面就可以直接生成這個bean了近弟。
14缅糟、spring+Hibernate中委托方案怎么配置?
解決方案一,按照Object[]數(shù)據(jù)取出數(shù)據(jù)藐吮,然后自己組bean
解決方案二溺拱,對每個表的bean寫構(gòu)造函數(shù)逃贝,比如表一要查出field1,field2兩個字段谣辞,那么有一個構(gòu)造函數(shù)就是Bean(type1filed1,type2
field2) ,然后在hql里面就可以直接生成這個bean了沐扳。
15泥从、spring+Hibernate中委托方案怎么配置?
解決方案一,按照Object[]數(shù)據(jù)取出數(shù)據(jù)沪摄,然后自己組bean
解決方案二躯嫉,對每個表的bean寫構(gòu)造函數(shù),比如表一要查出field1,field2兩個字段杨拐,那么有一個構(gòu)造函數(shù)就是Bean(type1filed1,type2
field2) 祈餐,然后在hql里面就可以直接生成這個bean了屏箍。
16. hibernate進(jìn)行多表查詢每個表中各取幾個字段仓坞,也就是說查詢出來的結(jié)果集沒有一個實體類與之對應(yīng)如何解決;
解決方案一氨距,按照Object[]數(shù)據(jù)取出數(shù)據(jù)屋吨,然后自己組bean
解決方案二蜒谤,對每個表的bean寫構(gòu)造函數(shù),比如表一要查出field1,field2兩個字段至扰,那么有一個構(gòu)造函數(shù)就是Bean(type1filed1,type2
field2) 鳍徽,然后在hql里面就可以直接生成這個bean了。
17.介紹一下Hibernate的二級緩存
按照以下思路來回答:(1)首先說清楚什么是緩存敢课,(2)再說有了hibernate的Session就是一級緩存阶祭,即有了一級緩存,為什么還要有二級緩存直秆,(3)最后再說如何配置Hibernate的二級緩存濒募。
(1)緩存就是把以前從數(shù)據(jù)庫中查詢出來和使用過的對象保存在內(nèi)存中(一個數(shù)據(jù)結(jié)構(gòu)中),這個數(shù)據(jù)結(jié)構(gòu)通常是或類似Hashmap切厘,當(dāng)以后要使用某個對象時萨咳,先查詢緩存中是否有這個對象,如果有則使用緩存中的對象疫稿,如果沒有則去查詢數(shù)據(jù)庫培他,并將查詢出來的對象保存在緩存中鹃两,以便下次使用。下面是緩存的偽代碼:
引出hibernate的第二級緩存舀凛,用下面的偽代碼分析了Cache的實現(xiàn)原理
Dao
{
hashmap map = newmap();
User getUser(integerid)
{
User user =map.get(id)
if(user ==null)
{
user =session.get(id);
map.put(id,user);
}
return user;
}
}
Dao
{
Cache cache = null
setCache(Cachecache)
{
this.cache =cache
}
User getUser(int id)
{
if(cache!=null)
{
Useruser = cache.get(id);
if(user==null)
{
user= session.get(id);
cache.put(id,user);
}
returnuser;
}
returnsession.get(id);
}
}
(2)Hibernate的Session就是一種緩存俊扳,我們通常將之稱為Hibernate的一級緩存,當(dāng)想使用session從數(shù)據(jù)庫中查詢出一個對象時猛遍,Session也是先從自己內(nèi)部查看是否存在這個對象馋记,存在則直接返回,不存在才去訪問數(shù)據(jù)庫懊烤,并將查詢的結(jié)果保存在自己內(nèi)部梯醒。由于Session代表一次會話過程,一個Session與一個數(shù)據(jù)庫連接相關(guān)連腌紧,所以Session最好不要長時間保持打開茸习,通常僅用于一個事務(wù)當(dāng)中,在事務(wù)結(jié)束時就應(yīng)關(guān)閉壁肋。并且Session是線程不安全的号胚,被多個線程共享時容易出現(xiàn)問題。通常只有那種全局意義上的緩存才是真正的緩存應(yīng)用浸遗,才有較大的緩存價值猫胁,因此,Hibernate的Session這一級緩存的緩存作用并不明顯跛锌,應(yīng)用價值不大弃秆。Hibernate的二級緩存就是要為Hibernate配置一種全局緩存,讓多個線程和多個事務(wù)都可以共享這個緩存察净。我們希望的是一個人使用過驾茴,其他人也可以使用,session沒有這種效果氢卡。
(3)二級緩存是獨立于Hibernate的軟件部件锈至,屬于第三方的產(chǎn)品,多個廠商和組織都提供有緩存產(chǎn)品译秦,例如峡捡,EHCache和OSCache等等。在Hibernate中使用二級緩存筑悴,首先就要在hibernate.cfg.xml配置文件中配置使用哪個廠家的緩存產(chǎn)品们拙,接著需要配置該緩存產(chǎn)品自己的配置文件,最后要配置Hibernate中的哪些實體對象要納入到二級緩存的管理中阁吝。明白了二級緩存原理和有了這個思路后砚婆,很容易配置起Hibernate的二級緩存。擴(kuò)展知識:一個SessionFactory可以關(guān)聯(lián)一個二級緩存突勇,也即一個二級緩存只能負(fù)責(zé)緩存一個數(shù)據(jù)庫中的數(shù)據(jù)装盯,當(dāng)使用Hibernate的二級緩存后坷虑,注意不要有其他的應(yīng)用或SessionFactory來更改當(dāng)前數(shù)據(jù)庫中的數(shù)據(jù),這樣緩存的數(shù)據(jù)就會與數(shù)據(jù)庫中的實際數(shù)據(jù)不一致埂奈。
18迄损、Spring的依賴注入是什么意思?給一個 Bean 的 message屬性,字符串類型,注入值為"Hello"的 XML配置文件該怎么寫?
19、Jdo是什么?
JDO是Java對象持久化的新的規(guī)范账磺,為java data object的簡稱,也是一個用于存取某種數(shù)據(jù)倉庫中的對象的標(biāo)準(zhǔn)化API芹敌。JDO提供了透明的對象存儲,因此對開發(fā)人員來說垮抗,存儲數(shù)據(jù)對象完全不需要額外的代碼(如JDBC API的使用)氏捞。這些繁瑣的例行工作已經(jīng)轉(zhuǎn)移到JDO產(chǎn)品提供商身上,使開發(fā)人員解脫出來借宵,從而集中時間和精力在業(yè)務(wù)邏輯上幌衣。另外,JDO很靈活壤玫,因為它可以在任何數(shù)據(jù)底層上運(yùn)行。JDBC只是面向關(guān)系數(shù)據(jù)庫(RDBMS)JDO更通用哼凯,提供到任何數(shù)據(jù)底層的存儲功能欲间,比如關(guān)系數(shù)據(jù)庫、文件断部、XML以及對象數(shù)據(jù)庫(ODBMS)等等猎贴,使得應(yīng)用可移植性更強(qiáng)。
20蝴光、什么是spring的IOCAOP
21她渴、STRUTS的工作流程!
22蔑祟、spring與EJB的區(qū)別L约瘛科平!
八.軟件工程與設(shè)計模式
1、UML方面
標(biāo)準(zhǔn)建模語言UML。用例圖,靜態(tài)圖(包括類圖浙踢、對象圖和包圖),行為圖,交互圖(順序圖,合作圖),實現(xiàn)圖。
2哭懈、j2ee常用的設(shè)計模式俘种?說明工廠模式。
總共23種篇亭,分為三大類:創(chuàng)建型缠捌,結(jié)構(gòu)型,行為型
我只記得其中常用的6译蒂、7種曼月,分別是:
創(chuàng)建型(工廠肃叶、工廠方法、抽象工廠十嘿、單例)
結(jié)構(gòu)型(包裝因惭、適配器,組合绩衷,代理)
行為(觀察者蹦魔,模版,策略)
然后再針對你熟悉的模式談?wù)勀愕睦斫饧纯伞?/p>
Java中的23種設(shè)計模式:
Factory(工廠模式)咳燕,Builder(建造模式)勿决,F(xiàn)actory Method(工廠方法模式),
Prototype(原始模型模式)招盲,Singleton(單例模式)低缩,F(xiàn)acade(門面模式),
Adapter(適配器模式)曹货,Bridge(橋梁模式)咆繁,Composite(合成模式),
Decorator(裝飾模式)顶籽,F(xiàn)lyweight(享元模式)玩般,Proxy(代理模式),
Command(命令模式)礼饱,Interpreter(解釋器模式)坏为, Visitor(訪問者模式),
Iterator(迭代子模式)镊绪,Mediator(調(diào)停者模式)匀伏,Memento(備忘錄模式),
Observer(觀察者模式)蝴韭,State(狀態(tài)模式)够颠,Strategy(策略模式),
Template Method(模板方法模式)万皿, Chain Of Responsibleity(責(zé)任鏈模式)
工廠模式:工廠模式是一種經(jīng)常被使用到的模式摧找,根據(jù)工廠模式實現(xiàn)的類可以根據(jù)提供的數(shù)據(jù)生成一組類中某一個類的實例,通常這一組類有一個公共的抽象父類并且實現(xiàn)了相同的方法牢硅,但是這些方法針對不同的數(shù)據(jù)進(jìn)行了不同的操作蹬耘。首先需要定義一個基類,該類的子類通過不同的方法實現(xiàn)了基類中的方法减余。然后需要定義一個工廠類综苔,工廠類可以根據(jù)條件生成不同的子類實例。當(dāng)?shù)玫阶宇惖膶嵗螅_發(fā)人員可以調(diào)用基類中的方法而不必考慮到底返回的是哪一個子類的實例如筛。
3堡牡、開發(fā)中都用到了那些設(shè)計模式?用在什么場合?
每個模式都描述了一個在我們的環(huán)境中不斷出現(xiàn)的問題,然后描述了該問題的解決方案的核心杨刨。通過這種方式晤柄,你可以無數(shù)次地使用那些已有的解決方案,無需在重復(fù)相同的工作妖胀。主要用到了MVC的設(shè)計模式芥颈。用來開發(fā)JSP/Servlet或者J2EE的相關(guān)應(yīng)用。簡單工廠模式等赚抡。
九. j2ee部分
1爬坑、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ī)上只要安裝一個瀏覽器(Browser),如Netscape Navigator或Internet Explorer献丑,服務(wù)器安裝Oracle末捣、Sybase、InFORMix或 SQL Server等數(shù)據(jù)庫创橄。在這種結(jié)構(gòu)下箩做,用戶界面完全通過WWW瀏覽器實現(xiàn),一部分事務(wù)邏輯在前端實現(xiàn)妥畏,但是主要事務(wù)邏輯在服務(wù)器端實現(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.對安全要求不同
C/S 一般面向相對固定的用戶群,對信息安全的控制能力很強(qiáng).一般高度機(jī)密的信息系統(tǒng)采用C/S結(jié)構(gòu)適宜.可以通過B/S發(fā)布部分可公開信息.
B/S 建立在廣域網(wǎng)之上,對安全的控制能力相對弱,可能面向不可知的用戶醉蚁。
3.對程序架構(gòu)不同
C/S 程序可以更加注重流程,可以對權(quán)限多層次校驗,對系統(tǒng)運(yùn)行速度可以較少考慮.
B/S 對安全以及訪問速度的多重的考慮,建立在需要更加優(yōu)化的基礎(chǔ)之上.比C/S有更高的要求 B/S結(jié)構(gòu)的程序架構(gòu)是發(fā)展的趨勢,從MS的.Net系列的BizTalk 2000Exchange 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 對的多重結(jié)構(gòu),要求構(gòu)件相對獨立的功能.能夠相對較好的重用.就入買來的餐桌可以再利用,而不是做在墻上的石頭桌子
5.系統(tǒng)維護(hù)不同
C/S 程序由于整體性,必須整體考察,處理出現(xiàn)的問題以及系統(tǒng)升級.升級難.可能是再做一個全新的系統(tǒng)
B/S 構(gòu)件組成,方面構(gòu)件個別的更換,實現(xiàn)系統(tǒng)的無縫升級.系統(tǒng)維護(hù)開銷減到最小.用戶從網(wǎng)上自己下載安裝就可以實現(xiàn)升級.
6.處理問題不同
C/S 程序可以處理用戶面固定,并且在相同區(qū)域,安全要求高需求,與操作系統(tǒng)相關(guān).應(yīng)該都是相同的系統(tǒng)
B/S 建立在廣域網(wǎng)上,面向不同的用戶群,分散地域,這是C/S無法作到的.與操作系統(tǒng)平臺關(guān)系最小.
7.用戶接口不同
C/S 多是建立的Window平臺上,表現(xiàn)方法有限,對程序員普遍要求較高
B/S 建立在瀏覽器上,有更加豐富和生動的表現(xiàn)方式與用戶交流.并且大部分難度減低,減低開發(fā)成本.
8.信息流不同
C/S 程序一般是典型的中央集權(quán)的機(jī)械式處理,交互性相對低
B/S 信息流向可變化, B-B B-C B-G等信息燃辖、流向的變化,更像交易中心。
2奈懒、應(yīng)用服務(wù)器與WEB SERVER的區(qū)別秋冰?
應(yīng)用服務(wù)器:Weblogic序宦、Tomcat辟癌、Jboss
WEB SERVER:IIS氏身、 Apache
3巍棱、應(yīng)用服務(wù)器有那些?
BEA WebLogic Server蛋欣,IBM WebSphere Application Server航徙,Oracle9i ApplicationServer,jBoss陷虎,Tomcat
4到踏、J2EE是什么?
答:Je22是Sun公司提出的多層(multi-diered),分布式(distributed),基于組件(component-base)的企業(yè)級應(yīng)用模型(enterpriese applicationmodel).在這樣的一個應(yīng)用系統(tǒng)中泻红,可按照功能劃分為不同的組件夭禽,這些組件又可在不同計算機(jī)上,并且處于相應(yīng)的層次(tier)中谊路。所屬層次包括客戶層(clietn tier)組件,web層和組件,Business層和組件,企業(yè)信息系統(tǒng)(EIS)層讹躯。
一個另類的回答:j2ee就是增刪改查。
5缠劝、J2EE是技術(shù)還是平臺還是框架潮梯?什么是J2EE
J2EE本身是一個標(biāo)準(zhǔn),一個為企業(yè)分布式應(yīng)用的開發(fā)提供的標(biāo)準(zhǔn)平臺惨恭。
J2EE也是一個框架秉馏,包括JDBC、JNDI脱羡、RMI萝究、JMS、EJB锉罐、JTA等技術(shù)帆竹。
6、請對以下在J2EE中常用的名詞進(jìn)行解釋(或簡單描述)
web容器:給處于其中的應(yīng)用程序組件(JSP脓规,SERVLET)提供一個環(huán)境栽连,使JSP,SERVLET直接更容器中的環(huán)境變量接口交互,不必關(guān)注其它系統(tǒng)問題侨舆。主要有WEB服務(wù)器來實現(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放入該容器沥割,馬上就會被容器進(jìn)行高效率的管理。并且可以通過現(xiàn)成的接口來獲得系統(tǒng)級別的服務(wù)凿菩。例如郵件服務(wù)机杜、事務(wù)管理。
JNDI:(Java Naming & Directory Interface)JAVA命名目錄服務(wù)衅谷。主要提供的功能是:提供一個目錄系統(tǒng)椒拗,讓其它各地的應(yīng)用程序在其上面留下自己的索引,從而滿足快速查找和定位分布式應(yīng)用程序的功能获黔。
JMS:(Java Message Service)JAVA消息服務(wù)蚀苛。主要實現(xiàn)各個應(yīng)用程序之間的通訊。包括點對點和廣播玷氏。
JTA:(Java Transaction API)JAVA事務(wù)服務(wù)堵未。提供各種分布式事務(wù)服務(wù)。應(yīng)用程序只需調(diào)用其提供的接口即可盏触。
JAF:(Java Action FrameWork)JAVA安全認(rèn)證框架渗蟹。提供一些安全控制方面的框架。讓開發(fā)者通過各種部署和自定義實現(xiàn)自己的個性安全控制策略赞辩。
RMI/IIOP:(Remote Method Invocation /internet對象請求中介協(xié)議)他們主要用于通過遠(yuǎn)程調(diào)用服務(wù)雌芽。例如,遠(yuǎn)程有一臺計算機(jī)上運(yùn)行一個程序辨嗽,它提供股票分析服務(wù)世落,我們可以在本地計算機(jī)上實現(xiàn)對其直接調(diào)用。當(dāng)然這是要通過一定的規(guī)范才能在異構(gòu)的系統(tǒng)之間進(jìn)行通信糟需。RMI是JAVA特有的屉佳。
7、如何給weblogic指定大小的內(nèi)存?
(這個問題不作具體回答洲押,列出來只是告訴讀者可能會遇到什么問題忘古,你不需要面面俱到,什么都精通诅诱。)
在啟動Weblogic的腳本中(位于所在Domian對應(yīng)服務(wù)器目錄下的startServerName),增加set MEM_ARGS=-Xms32m-Xmx200m送朱,可以調(diào)整最小內(nèi)存為32M娘荡,最大200M
8、如何設(shè)定的weblogic的熱啟動模式(開發(fā)模式)與產(chǎn)品發(fā)布模式?
可以在管理控制臺中修改對應(yīng)服務(wù)器的啟動模式為開發(fā)或產(chǎn)品模式之一驶沼∨阢澹或者修改服務(wù)的啟動文件或者commenv文件,增加setPRODUCTION_MODE=true回怜。
9大年、如何啟動時不需輸入用戶名與密碼?
修改服務(wù)啟動文件换薄,增加 WLS_USER和WLS_PW項。也可以在boot.properties文件中增加加密過的用戶名和密碼.
10翔试、在weblogic管理制臺中對一個應(yīng)用域(或者說是一個網(wǎng)站,Domain)進(jìn)行jms及ejb或連接池等相關(guān)信息進(jìn)行配置后,實際保存在什么文件中?
保存在此Domain的config.xml文件中轻要,它是服務(wù)器的核心配置文件。
11垦缅、說說weblogic中一個Domain的缺省目錄結(jié)構(gòu)?比如要將一個簡單的helloWorld.jsp放入何目錄下,然的在瀏覽器上就可打入http://主機(jī):端口號//helloword.jsp就可以看到運(yùn)行結(jié)果了?又比如這其中用到了一個自己寫的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)用將可以實現(xiàn)在瀏覽器上無需輸入應(yīng)用名嚼酝。
12、在weblogic中發(fā)布ejb需涉及到哪些配置文件
不同類型的EJB涉及的配置文件不同竟坛,都涉及到的配置文件包括ejb-jar.xml,weblogic-ejb-jar.xmlCMP實體Bean一般還需要weblogic-cmp-rdbms-jar.xml
13闽巩、如何在weblogic中進(jìn)行ssl配置與客戶端的認(rèn)證配置或說說j2ee(標(biāo)準(zhǔn))進(jìn)行ssl的配置?
缺省安裝中使用DemoIdentity.jks和DemoTrust.jksKeyStore實現(xiàn)SSL,需要配置服務(wù)器使用Enable SSL流码,配置其端口又官,在產(chǎn)品模式下需要從CA獲取私有密鑰和數(shù)字證書,創(chuàng)建identity和trust keystore漫试,裝載獲得的密鑰和數(shù)字證書六敬。可以配置此SSL連接是單向還是雙向的驾荣。
14外构、如何查看在weblogic中已經(jīng)發(fā)布的EJB?
可以使用管理控制臺,在它的Deployment中可以查看所有已發(fā)布的EJB
十. EBJ部分
1播掷、EJB是基于哪些技術(shù)實現(xiàn)的审编?并說出SessionBean和EntityBean的區(qū)別,StatefulBean和StatelessBean的區(qū)別歧匈。
EJB包括Session Bean垒酬、Entity Bean、Message Driven Bean件炉,基于JNDI勘究、RMI、JAT等技術(shù)實現(xiàn)斟冕。
SessionBean在J2EE應(yīng)用程序中被用來完成一些服務(wù)器端的業(yè)務(wù)操作口糕,例如訪問數(shù)據(jù)庫、調(diào)用其他EJB組件磕蛇。EntityBean被用來代表應(yīng)用系統(tǒng)中用到的數(shù)據(jù)景描。
對于客戶機(jī)十办,SessionBean是一種非持久性對象,它實現(xiàn)某些在服務(wù)器上運(yùn)行的業(yè)務(wù)邏輯超棺。
對于客戶機(jī)向族,EntityBean是一種持久性對象,它代表一個存儲在持久性存儲器中的實體的對象視圖说搅,或是一個由現(xiàn)有企業(yè)應(yīng)用程序?qū)崿F(xiàn)的實體炸枣。
Session Bean 還可以再細(xì)分為 Stateful Session Bean與 Stateless SessionBean,這兩種的 Session Bean都可以將系統(tǒng)邏輯放在 method之中執(zhí)行弄唧,不同的是 Stateful SessionBean可以記錄呼叫者的狀態(tài)适肠,因此通常來說,一個使用者會有一個相對應(yīng)的 Stateful SessionBean的實體候引。Stateless SessionBean雖然也是邏輯組件侯养,但是他卻不負(fù)責(zé)記錄使用者狀態(tài),也就是說當(dāng)使用者呼叫 Stateless SessionBean的時候澄干,EJB Container并不會找尋特定的 Stateless SessionBean的實體來執(zhí)行這個 method逛揩。換言之,很可能數(shù)個使用者在執(zhí)行某個 Stateless SessionBean的 methods時麸俘,會是同一個 Bean的 Instance在執(zhí)行辩稽。從內(nèi)存方面來看, Stateful SessionBean與Stateless SessionBean比較从媚, Stateful SessionBean會消耗 J2EE Server較多的內(nèi)存逞泄,然而 Stateful SessionBean的優(yōu)勢卻在于他可以維持使用者的狀態(tài)。
2拜效、簡要講一下 EJB的 7個 Transaction Level?
3喷众、EJB與JAVA BEAN的區(qū)別?
Java Bean 是可復(fù)用的組件紧憾,對Java Bean并沒有嚴(yán)格的規(guī)范到千,理論上講,任何一個Java類都可以是一個Bean赴穗。但通常情況下憔四,由于Java Bean是被容器所創(chuàng)建(如Tomcat)的,所以Java Bean應(yīng)具有一個無參的構(gòu)造器般眉,另外加矛,通常Java Bean還要實現(xiàn)Serializable接口用于實現(xiàn)Bean的持久性。Java Bean實際上相當(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ī))鸠窗。但EJB必須被布署在諸如Webspere妓羊、WebLogic這樣的容器中,EJB客戶從不直接訪問真正的EJB組件稍计,而是通過其容器訪問躁绸。EJB容器是EJB組件的代理,EJB組件由容器所創(chuàng)建和管理臣嚣【还危客戶通過容器來訪問真正的EJB組件。
4硅则、EJB包括(SessionBean,EntityBean)說出他們的生命周期淹父,及如何管理事務(wù)的?
SessionBean:Stateless Session Bean的生命周期是由容器決定的怎虫,當(dāng)客戶機(jī)發(fā)出請求要建立一個Bean的實例時暑认,EJB容器不一定要創(chuàng)建一個新的Bean的實例供客戶機(jī)調(diào)用,而是隨便找一個現(xiàn)有的實例提供給客戶機(jī)大审。當(dāng)客戶機(jī)第一次調(diào)用一個Stateful SessionBean 時症见,容器必須立即在服務(wù)器中創(chuàng)建一個新的Bean實例台谊,并關(guān)聯(lián)到客戶機(jī)上,以后此客戶機(jī)調(diào)用Stateful SessionBean的方法時容器會把調(diào)用分派到與此客戶機(jī)相關(guān)聯(lián)的Bean實例。
EntityBean:Entity Beans能存活相對較長的時間睡汹,并且狀態(tài)是持續(xù)的。只要數(shù)據(jù)庫中的數(shù)據(jù)存在扇商,Entity beans就一直存活毒姨。而不是按照應(yīng)用程序或者服務(wù)進(jìn)程來說的。即使EJB容器崩潰了溶浴,Entity beans也是存活的乍迄。Entity Beans生命周期能夠被容器或者 Beans自己管理。
EJB通過以下技術(shù)管理實務(wù):對象管理組織(OMG)的對象實務(wù)服務(wù)(OTS)士败,Sun Microsystems的Transaction Service(JTS)闯两、Java Transaction API(JTA),開發(fā)組(X/Open)的XA接口谅将。
5漾狼、EJB容器提供的服務(wù)
主要提供聲明周期管理、代碼產(chǎn)生饥臂、持續(xù)性管理逊躁、安全、事務(wù)管理隅熙、鎖和并發(fā)行管理等服務(wù)稽煤。
6核芽、EJB的激活機(jī)制
以Stateful Session Bean為例:其Cache大小決定了內(nèi)存中可以同時存在的Bean實例的數(shù)量,根據(jù)MRU或NRU算法酵熙,實例在激活和去激活狀態(tài)之間遷移轧简,激活機(jī)制是當(dāng)客戶端調(diào)用某個EJB實例業(yè)務(wù)方法時,如果對應(yīng)EJB Object發(fā)現(xiàn)自己沒有綁定對應(yīng)的Bean實例則從其去激活Bean存儲中(通過序列化機(jī)制存儲實例)回復(fù)(激活)此實例匾二。狀態(tài)變遷前會調(diào)用對應(yīng)的ejbActive和ejbPassivate方法哮独。
7、EJB的幾種類型
會話(Session)Bean察藐,實體(Entity)Bean消息驅(qū)動的(Message Driven)Bean
會話Bean又可分為有狀態(tài)(Stateful)和無狀態(tài)(Stateless)兩種
實體Bean可分為Bean管理的持續(xù)性(BMP)和容器管理的持續(xù)性(CMP)兩種
8皮璧、客服端調(diào)用EJB對象的幾個基本步驟
設(shè)置JNDI服務(wù)工廠以及JNDI服務(wù)地址系統(tǒng)屬性,查找Home接口转培,從Home接口調(diào)用Create方法創(chuàng)建Remote接口恶导,通過Remote接口調(diào)用其業(yè)務(wù)方法。
十一. webservice部分
1浸须、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)你需要改變具體的實現(xiàn)時候也不需要修改代碼。
JAXM(Java API for XML Messaging) 是為SOAP通信提供訪問方法和傳輸機(jī)制的API梢灭。
WSDL是一種 XML格式夷家,用于將網(wǎng)絡(luò)服務(wù)描述為一組端點,這些端點對包含面向文檔信息或面向過程信息的消息進(jìn)行操作敏释。這種格式首先對操作和消息進(jìn)行抽象描述库快,然后將其綁定到具體的網(wǎng)絡(luò)協(xié)議和消息格式上以定義端點。相關(guān)的具體端點即組合成為抽象端點(服務(wù))钥顽。
SOAP即簡單對象訪問協(xié)議(Simple Object Access Protocol)义屏,它是用于交換XML編碼信息的輕量級協(xié)議。
UDDI 的目的是為電子商務(wù)建立標(biāo)準(zhǔn);UDDI是一套基于Web的湿蛔、分布式的膀曾、為Web Service提供的、信息注冊中心的實現(xiàn)標(biāo)準(zhǔn)規(guī)范阳啥,同時也包含一組使企業(yè)能將自身提供的Web Service注冊,以使別的企業(yè)能夠發(fā)現(xiàn)的訪問協(xié)議的實現(xiàn)標(biāo)準(zhǔn)财喳。
2察迟、CORBA是什么?用途是什么?
CORBA 標(biāo)準(zhǔn)是公共對象請求代理結(jié)構(gòu)(Common Object Request Broker Architecture),由對象管理組織 (Object ManagementGroup耳高,縮寫為 OMG)標(biāo)準(zhǔn)化扎瓶。它的組成是接口定義語言(IDL),語言綁定(binding:也譯為聯(lián)編)和允許應(yīng)用程序間互操作的協(xié)議。其目的為:用不同的程序設(shè)計語言書寫在不同的進(jìn)程中運(yùn)行泌枪,為不同的操作系統(tǒng)開發(fā)概荷。
3. Linux
4、LINUX下線程碌燕,GDI類的解釋误证。
LINUX實現(xiàn)的就是基于核心輕量級進(jìn)程的"一對一"線程模型,一個線程實體對應(yīng)一個核心輕量級進(jìn)程修壕,而線程之間的管理在核外函數(shù)庫中實現(xiàn)愈捅。
GDI類為圖像設(shè)備編程接口類庫。
5. 問得稀里糊涂的題
6慈鸠、四種會話跟蹤技術(shù)
會話作用域ServletsJSP頁面描述
page否是代表與一個頁面相關(guān)的對象和屬性蓝谨。一個頁面由一個編譯好的 Java servlet類(可以帶有任何的include指令,但是沒有 include動作)表示青团。這既包括 servlet又包括被編譯成 servlet的 JSP頁面
request是是代表與 Web客戶機(jī)發(fā)出的一個請求相關(guān)的對象和屬性譬巫。一個請求可能跨越多個頁面,涉及多個Web組件(由于 forward指令和 include動作的關(guān)系)
session是是代表與用于某個 Web客戶機(jī)的一個用戶體驗相關(guān)的對象和屬性督笆。一個 Web會話可以也經(jīng)常會跨越多個客戶機(jī)請求
application是是代表與整個 Web應(yīng)用程序相關(guān)的對象和屬性芦昔。這實質(zhì)上是跨越整個 Web應(yīng)用程序,包括多個頁面胖腾、請求和會話的一個全局作用域
7调窍、簡述邏輯操作(&,|,^)與條件操作(&&,||)的區(qū)別。
區(qū)別主要答兩點:a.條件操作只能操作布爾型的,而邏輯操作不僅可以操作布爾型,而且可以操作數(shù)值型
b.邏輯操作不會產(chǎn)生短路
十二.其他
1围小、請用英文簡單介紹一下自己.
4们豌、WEB SERVICE名詞解釋。JSWDL開發(fā)包的介紹记罚。JAXP墅诡、JAXM的解釋。SOAP、UDDI,WSDL解釋末早。
2烟馅、請把http://tomcat.apache.org/首頁的這一段話用中文翻譯一下?
Apache Tomcat is the servlet container that is used in the officialReference Implementation for theJava ServletandJavaServerPagestechnologies. The Java Servlet and JavaServer Pagesspecifications are developed by Sun under theJavaCommunity Process.
Apache Tomcat is developed in an open andparticipatory environment and released under theApacheSoftware License. Apache Tomcat is intended to be a collaboration ofthe best-of-breed developers from around the world. We invite you toparticipate in this open development project. To learn more about gettinginvolved,click here.
ApacheTomcat powers numerous large-scale, mission-critical web applications across adiverse range of industries and organizations. Some of these users and theirstories are listed on thePoweredBywiki page.
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 itthread 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 tableas 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 youused ,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?
Administrator 10:34:20
1然磷,堆和棧的區(qū)別郑趁,有一個64k的字符串,是放到堆上姿搜,還是放到棧上寡润,為什么?
2舅柜,什么時候用到接口梭纹,什么時候用到抽象類,二者區(qū)別
3致份,有一個100萬的數(shù)組变抽,里邊有兩個市重復(fù)的,如何設(shè)計算法找到氮块。
4绍载,設(shè)計數(shù)據(jù)庫時,n維雇锡,如何設(shè)計逛钻。
例如[省份][城市][網(wǎng)吧],這是三維關(guān)系锰提,它的表也應(yīng)該有三個曙痘,網(wǎng)吧有外鍵引用城市,城市有外鍵應(yīng)用省份立肘,這個規(guī)律就是下層的要有一外鍵去引用上層边坤。