第一篇:農(nóng)業(yè)銀行Java基礎(chǔ)面試題
基礎(chǔ)測試
基礎(chǔ)知識部分:
1.談?wù)刦inal, finally, finalize的區(qū)別。
final 用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。finally 是異常處理語句結(jié)構(gòu)的一部分,表示總是執(zhí)行。finalize 是 Object 類的一個方法,在垃圾收集器執(zhí)行的時候會調(diào)用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關(guān)閉文件等。
2.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 算法都大概一樣,所以性能不會有很大的差異。
3.public,private,protected,friendly,internal 的作用范圍。
private 同一個類中
protected 同一類中,同一包中,不同包中的該類子類
public 同一類中,同一包中,不同包中的該類子類,不同包中的該類的非子類
friendly 同一個類中,同一包中
internal 表示在同一個應(yīng)用程序(Application)或類庫(Library)中都可以使用,不過這個我們基本上不用 4.Java的接口和抽象類的區(qū)別。
接口中的方法只能是定義不可以有實現(xiàn),而且所有成員默認(rèn)均為公有的,實現(xiàn)接口時必須實現(xiàn)該接口定義的所有方法。接口可以多重繼承。而抽象類中則可以存在私有成員,方法允許有實現(xiàn),繼承抽象后可以不去實現(xiàn)該抽象類的抽象方法,但此時該子類也必須聲明為抽象類。抽象類不能多重繼承。
5.在java中一個類被聲明為final類型,表示了什么意思?
final—修飾符(關(guān)鍵字)如果一個類被聲明為final,意味著它不能再派生出新的子類,不能作為父類被繼承。因此一個類不能既被聲明為abstract的,又被聲明為final的。將變量或方法聲明為final,可以保證它們在使用中不被改變。被聲明為final的變量必須在聲明時給定初值,而在以后的引用中只能讀取,不可修改。被聲明為final的方法也同樣只能使用,不能重載
6.heap和stack有什么區(qū)別。
棧是一種線形集合,其添加和刪除元素的操作應(yīng)在同一段完成。棧按照后進(jìn)先出的方式進(jìn)行處理。堆是棧的一個組成元素
7.Overload和Override的區(qū)別。Overloaded的方法是否可以改變返回值的類
型?
Overloaded 的方法是否可以改變返回值的類型 ?方法的重寫 Overriding 和重載 Overloading 是 Java 多態(tài)性的不同表現(xiàn)。重寫 Overriding 是父類與子類之間多態(tài)性的一種表現(xiàn),重載 Overloading 是一個類中多態(tài)性的一種表現(xiàn)。如果在子類中定義某方法與其父類有相同的名稱和參數(shù),我們說該方法被重寫(Overriding)。子類的對象使用這個方法時,將調(diào)用子類中的定義,對它而言,父類中的定義如同被“屏蔽”了。如果在一個類中定義了多個同名的方法,它們或有不同的參數(shù)個數(shù)或有不同的參數(shù)類型,則稱為方法的重載(Overloading)。Overloaded 的方法是可以改變返回值的類型。
8.GC是什么? 為什么要有GC?(基礎(chǔ))。
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)存的顯示操作方法。
9.Collection 和 Collections的區(qū)別。
Collection 是集合類的上級接口,繼承與他的接口主要有 Set 和 List.Collections 是針對集合類的一個幫助類,他提供一系列靜態(tài)方法實現(xiàn)對各種集合的搜索、排序、線程安全化等操作。
10.Anonymous Inner Class(匿名內(nèi)部類)是否可以extends(繼承)其它類,是
否可以implements(實現(xiàn))interface(接口)?
匿名的內(nèi)部類是沒有名字的內(nèi)部類。不能extends(繼承)其它類,但一個內(nèi)部類可以作為一個接口,由另一個內(nèi)部類實現(xiàn)。
11.Static Nested Class 和 Inner Class的不同
Static Nested Class 是被聲明為靜態(tài)(static)的內(nèi)部類,它可以不依賴于外部類實例被實例化。而通常的內(nèi)部類需要在外部類實例化后才能實例化。
12.什么時候用assert?
assertion(斷言)在軟件開發(fā)中是一種常用的調(diào)試方式,很多開發(fā)語言中都支持這種機(jī)制。在實現(xiàn)中,assertion 就是在程序中的一條語句,它對一個 boolean 表達(dá)式進(jìn)行檢查,一個正確程序必須保證這個 boolean 表達(dá)式的值為 true ;如果該值為 false,說明程序已經(jīng)處于不正確的狀態(tài)下,系統(tǒng)將給出警告或退出。一般來說,assertion 用于保證程序最基本、關(guān)鍵的正確性。assertion 檢查通常在開發(fā)和測試時開啟。為了提高性能,在軟件發(fā)布后,assertion 檢查通常是關(guān)閉的。
13.Java中的異常處理機(jī)制的簡單原理和應(yīng)用。
當(dāng)JAVA程序違反了JAVA的語義規(guī)則時,JAVA虛擬機(jī)就會將發(fā)生的錯誤表示為一個異常。違反語義規(guī)則包括2種情況。一種是JAVA類庫內(nèi)置的語義檢查。例如數(shù)組下標(biāo)越界,會引發(fā)IndexOutOfBoundsException;訪問null的對象時會引發(fā)NullPointerException。另一種情況就是JAVA允許程序員擴(kuò)展這種語義檢查,程序員可以創(chuàng)建自己的異常,并自由選擇在何時用throw關(guān)鍵字引發(fā)異常。所有的異常都是java.lang.Thowable的子類。
14.垃圾回收的優(yōu)點(diǎn)和原理。并考慮2種回收機(jī)制。
Java語言中一個顯著的特點(diǎn)就是引入了垃圾回收機(jī)制,使c++程序員最頭疼的內(nèi)存管理的問題迎刃而解,它使得Java程序員在編寫程序的時候不再需要考慮內(nèi)存管理。由于有個垃圾回收機(jī)制,Java中的對象不再有“作用域”的概念,只有對象的引用才有“作用域”。垃圾回收可以有效的防止內(nèi)存泄露,有效的使用可以使用的內(nèi)存。垃圾回收器通常是作為一個單獨(dú)的低級別的線程運(yùn)行,不可預(yù)知的情況下對內(nèi)存堆中已經(jīng)死亡的或者長時間沒有使用的對象進(jìn)行清楚和回收,程序員不能實時的調(diào)用垃圾回收器對某個對象或所有對象進(jìn)行垃圾回收?;厥諜C(jī)制有分代復(fù)制垃圾回收和標(biāo)記垃圾回收,增量垃圾回收。
15.請說出你所知道的線程同步的方法。
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)的線程,注意并不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。
16.Error與Exception有什么區(qū)別?
error 表示恢復(fù)不是不可能但很困難的情況下的一種嚴(yán)重問題。比如說內(nèi)存溢出。不可能指望程序能處理這樣的情況。
exception 表示一種設(shè)計或?qū)崿F(xiàn)問題。也就是說,它表示如果程序運(yùn)行正常,從不會發(fā)生的情況。17.String s = new String(“abcdefghijklmn”);創(chuàng)建了幾個String Object? 兩
個
18.Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math.round(11.5)==12
Math.round(-11.5)==-11
round方法返回與參數(shù)最接近的長整數(shù),參數(shù)加1/2后求其floor.19.sleep()和 wait()有什么區(qū)別?
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)。
20.Java有沒有g(shù)oto? java中的保留字,現(xiàn)在沒有在java中使用。
21.數(shù)組有沒有l(wèi)ength()這個方法? String有沒有l(wèi)ength()這個方法?
數(shù)組沒有l(wèi)ength()這個方法,有l(wèi)ength的屬性。String有l(wèi)ength()這個方法。
22.JAVA類在什么情況下要實現(xiàn)java.io.Serializable接口?
23.給我一個你最常見到的runtime exception。
ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException
24.構(gòu)造器Constructor是否可被override?
構(gòu)造器Constructor不能被繼承,因此不能重寫Overriding,但可以被重載Overloading。
25.List, Set, Map是否繼承自Collection接口?List,Set是,Map不是
編程題:
1.輸出9*9口訣
2,寫一個Singleton出來。
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 static Singleton instance = new Singleton();
//這里提供了一個供外部訪問本class的靜態(tài)方法,可以直接訪問public static Singleton 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)為第一種形式要更加安全些
第二篇:java面試題(基礎(chǔ)部分)
Overload和Override的區(qū)別。Overloaded的方法是否可以改變返回值的類型?
方法的重寫Overriding和重載Overloading是Java多態(tài)性的不同表現(xiàn)。重寫Overriding是父類與子類之間多態(tài)性的一種表現(xiàn),重載Overloading是一個類中多態(tài)性的一種表現(xiàn)。如果在子類中定義某方法與其父類有相同的名稱和參數(shù),我們說該方法被重寫(Overriding)。子類的對象使用這個方法時,將調(diào)用子類中的定義,對它而言,父類中的定義如同被“屏蔽”了。如果在一個類中定義了多個同名的方法,它們或有不同的參數(shù)個數(shù)或有不同的參數(shù)類型,則稱為方法的重載(Overloading)。
Overloaded的方法是可以改變返回值的類型。數(shù)組有沒有l(wèi)ength()這個方法? String有沒有l(wèi)ength()這個方法?數(shù)組沒有l(wèi)ength()這個方法,有l(wèi)ength的屬性。
String有有l(wèi)ength()這個方法。Set里的元素是不能重復(fù)的,那么用什么方法來區(qū)分重復(fù)與否呢? 是用==還是equals()? 它們有何區(qū)別?
Set里的元素是不能重復(fù)的,那么用iterator()方法來區(qū)分重復(fù)與否。equals()是判讀兩個Set是否相等。equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋,為的是當(dāng)兩個分離的對象的內(nèi)容和類型相配的話,返回真值。
24最常見到的runtime exception。
ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException,EmptyStackException, IllegalArgumentException,IllegalMonitorStateException, IllegalPathStateException,IllegalStateException,ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException,NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFORMatException, Secur
ityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationExceptionerror和exception有什么區(qū)別?
error 表示恢復(fù)不是不可能但很困難的情況下的一種嚴(yán)重問題。比如說內(nèi)存溢出。不可能指望程序能處理這樣的情況。
exception 表示一種設(shè)計或?qū)崿F(xiàn)問題。也就是說,它表示如果程序運(yùn)行正常,從不會發(fā)生的情況。abstract class和interface有什么區(qū)別?
聲明方法的存在而不去實現(xiàn)它的類被叫做抽象類(abstract class),它用于要創(chuàng)建一個體現(xiàn)某些基本行為的類,并為該類聲明方法,但不能在該類中實現(xiàn)該類的情況。不能創(chuàng)建abstract 類的實例。然而可以創(chuàng)建一個變量,其類型是一個抽象類,并讓它指向具體子類的一個實例。不能有抽象構(gòu)造函數(shù)或抽象靜態(tài)方法。Abstract 類的子類為它們父類中的所有抽象方法提供實現(xiàn),否則它們也是抽象類為。取而代之,在子類中實現(xiàn)該方法。知道其行為的其它類可以在類中實現(xiàn)這些方法。
接口(interface)是抽象類的變體。在接口中,所有方法都是抽象的。多繼承性可通過實現(xiàn)這樣的接口而獲得。接口中的所有方法都是抽象的,沒有一個有程序體。接口只可以定義static final成員變量。接口的實現(xiàn)與子類相似,除了該實現(xiàn)類不能從接口定義中繼承行為。當(dāng)類實現(xiàn)特殊接口時,它定義(即將程序體給予)所有這種接口的方法。然后,它可以在實現(xiàn)了該接口的類的任何對象上調(diào)用接口的方法。由于有抽象類,它允許使用接口名作為引用變量的類型。通常的動態(tài)聯(lián)編將生效。引用可以轉(zhuǎn)換到接口類型或從接口類型轉(zhuǎn)換,instanceof 運(yùn)算符可以用來決定某對象的類是否實現(xiàn)了接口。abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized?
都不能接口是否可繼承接口? 抽象類是否可實現(xiàn)(implements)接口? 抽象類是否可繼承實體類(concrete class)?
接口可以繼承接口。抽象類可以實現(xiàn)(implements)接口,抽象類可繼承實體類,但前提是實體類必須有明確的構(gòu)造函數(shù)。啟動一個線程是用run()還是start()?
啟動一個線程是調(diào)用start()方法,使線程所代表的虛擬處理機(jī)處于可運(yùn)行狀態(tài),這意味著它可以由JVM調(diào)度并執(zhí)行。這并不意味著線程就會立即運(yùn)行。run()方法可以產(chǎn)生必須退出的標(biāo)志來停止一個線程。
是否可以繼承String類?
String類是final類故不可以繼承。
構(gòu)造器Constructor是否可被override?
構(gòu)造器Constructor不能被繼承,因此不能重寫Overriding,但可以被重載Overloading。
當(dāng)一個線程進(jìn)入一個對象的一個synchronized方法后,其它線程是否可進(jìn)入此對象的其它方法?
不能,一個對象的一個synchronized方法只能由一個線程訪問。
33try {}里有一個return語句,那么緊跟在這個try后的finally {}里的code會不
會被執(zhí)行,什么時候被執(zhí)行,在return前還是后?
會執(zhí)行,在return前執(zhí)行。
編程題: 用最有效率的方法算出2乘以8等於幾?<< 3
兩個對象值相同(x.equals(y)== true),但卻可有不同的hash code,這句話對不對?
不對,有相同的hash code。
36當(dāng)一個對象被當(dāng)作參數(shù)傳遞到一個方法后,此方法可改變這個對象的屬性,并可返回變化后的結(jié)果,那么這里到底是值傳遞還是引用傳遞?
是值傳遞。Java編程語言只由值傳遞參數(shù)。當(dāng)一個對象實例作為一個參數(shù)被傳遞到方法中時,參數(shù)的值就是對該對象的引用。對象的內(nèi)容可以在被調(diào)用的方法中改變,但對象的引用是永遠(yuǎn)不會改變的。
37swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
switch(expr1)中,expr1是一個整數(shù)表達(dá)式。因此傳遞給 switch 和 case 語句的參數(shù)應(yīng)該是 int、short、char 或者 byte。long,string 都不能作用于swtich。
Hashtable和HashMap
Hashtable繼承自Dictionary類,而HashMap是Java1.2引進(jìn)的Map interface的一個實現(xiàn)
HashMap允許將null作為一個entry的key或者value,而Hashtable不允許
還有就是,HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因為contains方法容易讓人引起誤解。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多個線程訪問Hashtable時,不需要自己為它的方法實現(xiàn)同步,而HashMap就必
須為之提供外同步。
Hashtable和HashMap采用的hash/rehash算法都大概一樣,所以性能不會有很大的差異。
1.Java的接口和C++的虛類的相同和不同處。
由于Java不支持多繼承,而有可能某個類或?qū)ο笠褂梅謩e在幾個類或?qū)ο罄锩娴姆椒ɑ驅(qū)傩?,現(xiàn)有的單繼承機(jī)制就不能滿足要求。與繼承相比,接口有更高的靈活性,因為接口中沒有任何實現(xiàn)代碼。當(dāng)一個類實現(xiàn)了接口以后,該類要實現(xiàn)接口里面所有的方法和屬性,并且接口里面的屬性在默認(rèn)狀態(tài)下面都是
public static,所有方法默認(rèn)情況下是public.一個類可以實現(xiàn)多個接口。
2.Java中的異常處理機(jī)制的簡單原理和應(yīng)用。
當(dāng)Java程序違反了Java的語義規(guī)則時,Java虛擬機(jī)就會將發(fā)生的錯誤表示為一個異常。違反語義規(guī)則包括2種情況。一種是Java類庫內(nèi)置的語義檢查。例如數(shù)組下標(biāo)越界,會引發(fā)IndexOutOfBoundsException;訪問null的對象時會引發(fā)NullPointerException。另一種情況就是Java允許程序員擴(kuò)展這種語義檢查,程序員可以創(chuàng)建自己的異常,并自由選擇在何時用throw關(guān)鍵字引發(fā)異常。所有的異常都是java.lang.Thowable的子類。
3.垃圾回收的優(yōu)點(diǎn)和原理。并考慮2種回收機(jī)制。
Java語言中一個顯著的特點(diǎn)就是引入了垃圾回收機(jī)制,使c++程序員最頭疼的內(nèi)存管理的問題迎刃而解,它使得Java程序員在編寫程序的時候不再需要考慮內(nèi)存管理。由于有個垃圾回收機(jī)制,Java中的對象不再有“作用域”的概念,只有對象的引用才有“作用域”。垃圾回收可以有效的防止內(nèi)存泄露,有效的使用可以使用的內(nèi)存。垃圾回收器通常是作為一個單獨(dú)的低級別的線程運(yùn)行,不可預(yù)知的情況下對內(nèi)存堆中已經(jīng)死亡的或者長時間沒有使用的對象進(jìn)行清除和回收,程序員不能實時的調(diào)用垃圾回收器對某個對象或所有對象進(jìn)行垃圾回收?;厥諜C(jī)制有分代復(fù)制垃圾回收和標(biāo)記垃圾回收,增量垃圾回收。
4.線程同步的方法。
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)的線程,注意并不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。
5.Error與Exception有什么區(qū)別?
Error表示系統(tǒng)級的錯誤和程序不必處理的異常,Exception表示需要捕捉或者需要程序進(jìn)行處理的異常。
6.在java中一個類被聲明為final類型,表示了什么意思?
表示該類不能被繼承,是頂級類。heap和stack有什么區(qū)別。
棧是一種線形集合,其添加和刪除元素的操作應(yīng)在同一段完成。棧按照后進(jìn)先出的方式進(jìn)行處理。堆是棧的一個組成元素。
8談?wù)刦inal, finally, finalize的區(qū)別。
final—修飾符(關(guān)鍵字)如果一個類被聲明為final,意味著它不能再派生出新的子類,不能作為父類被繼承。因此一個類不能既被聲明為 abstract的,又被聲明為final的。將變量或方法聲明為final,可以保證它們在使用中不被改變。被聲明為final的變量必須在聲明時給定初值,而在以后的引用中只能讀取,不可修改。被聲明為final的方法也同樣只能使用,不能重載。
finally—異常處理時提供 finally 塊來執(zhí)行任何清除操作。如果拋出一個異常,那么相匹配的 catch 子句就會執(zhí)行,然后控制就會進(jìn)入 finally 塊(如果有的話)。
finalize—方法名。Java 技術(shù)允許使用 finalize()方法在垃圾收集器將對象從內(nèi)存中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在確定這個對象沒有被引用時對這個對象調(diào)用的。它是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize()方法以整理系統(tǒng)資源或者執(zhí)行其他清理工作。finalize()方法是在垃圾收集器刪除對象之前對這個對象調(diào)用的。9Anonymous Inner Class(匿名內(nèi)部類)是否可以extends(繼承)其它類,是否可以implements(實現(xiàn))interface(接口)?
匿名的內(nèi)部類是沒有名字的內(nèi)部類。不能extends(繼承)其它類,但一個內(nèi)部類可以作為一個接口,由另一個內(nèi)部類實現(xiàn)。
10Static Nested Class 和 Inner Class的不同
Nested Class(一般是C++的說法),Inner Class(一般是JAVA的說法)。Java內(nèi)部類與C++嵌套類最大的不同就在于是否有指向外部的引用上。
注: 靜態(tài)內(nèi)部類(Inner Class)意味著1創(chuàng)建一個static內(nèi)部類的對象,不需要一個外部類對象,2不能從一個static內(nèi)部類的一個對象訪問一個外部類對象.
第三篇:JAVA面試題
1、面向?qū)ο蟮乃膫€特征:封裝、繼承、多態(tài)、抽象
封裝:
繼承:子類繼承父類,除private修飾以外的所以方法和屬性 多態(tài):一個對象多種狀態(tài),可以把子類對象當(dāng)作父類對象來看,一旦這樣做了,就只能
去調(diào)用父類中原有定義的屬性和方法,也就是子類中擴(kuò)展的方法或?qū)傩跃筒荒苷{(diào)用了。
抽象:
2、abstractclass 和interface的區(qū)別
聲明方法的存在而不去實現(xiàn)它的類被叫做抽象類(abstract class),它用于要創(chuàng)建一個體現(xiàn)某些基本行為的類,并為該類聲明方法,但不能在該類中實現(xiàn)該類的情況。不能創(chuàng)建abstract 類的實例。然而可以創(chuàng)建一個變量,其類型是一個抽象類,并讓它指向具體子類的一個實例。不能有抽象構(gòu)造函數(shù)或抽象靜態(tài)方法。Abstract 類的子類為它們父類中的所有抽象方法提供實現(xiàn),否則它們也是抽象類為。取而代之,在子類中實現(xiàn)該方法。知道其行為的其它類可以在類中實現(xiàn)這些方法。
接口(interface)是抽象類的變體。在接口中,所有方法都是抽象的。多繼承性可通過實現(xiàn)這樣的接口而獲得。接口中的所有方法都是抽象的,沒有一個有程序體。接口只可以定義static final成員變量。接口的實現(xiàn)與子類相似,除了該實現(xiàn)類不能從接口定義中繼承行為。當(dāng)類實現(xiàn)特殊接口時,它定義(即將程序體給予)所有這種接口的方法。然后,它可以在實現(xiàn)了該接口的類的任何對象上調(diào)用接口的方法。由于有抽象類,它允許使用接口名作為引用變量的類型。通常的動態(tài)聯(lián)編將生效。引用可以轉(zhuǎn)換到接口類型或從接口類型轉(zhuǎn)換,instanceof 運(yùn)算符可以用來決定某對象的類是否實現(xiàn)了接口。
3、final、finally、finalize的區(qū)別
final 用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。finally是異常處理語句結(jié)構(gòu)的一部分,表示總是執(zhí)行。
finalize是Object類的一個方法,在垃圾收集器執(zhí)行的時候會調(diào)用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關(guān)閉文件等。
4、匿名內(nèi)部類是否可以作為父類被其他類繼承,或做為接口被實現(xiàn)?
匿名內(nèi)部類不被繼承也不能被實現(xiàn),因為它沒有名字,而一個內(nèi)部類只要有名字就可以作為父類被繼承,也可以作為借口被實現(xiàn)。
5、多線程有幾種實現(xiàn)方法,同步有幾種實現(xiàn)方法,都是什么?
多線程有兩種實現(xiàn)方法,分別繼承繼承Thread類與實現(xiàn)runnable借口。
同步的實現(xiàn)方法有兩種,分別是synchronized,wait與notify。
6、string 與 stringbuffer的區(qū)別?
String的長度是不可變的,而stringbuffer的長度是可變的。如果你對字符中的內(nèi)容經(jīng)常進(jìn)行操作,特別是內(nèi)容修改時,那么就要使用stringbuffer,如果最后需要使用string,那么使用stringbuffer的tostring()方法。
7、解析XML文件的幾種方式和區(qū)別
DOM:處理大型文件時其性能下降的非常厲害
SAX:SAX是事件驅(qū)動型的XML解析方式,它是順序讀取XML文件,不需要一次性全部裝載整個文件。
8、sleep()和wait()有什么區(qū)別?
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)。
9、數(shù)組有沒有l(wèi)ength這個方法?string有沒有l(wèi)ength這個方法?
數(shù)組沒有l(wèi)ength()這個方法,有l(wèi)ength這個屬性
String有l(wèi)ength()這個方法
10、LinkedList、ArrayList和Vector的區(qū)別? ArrayList和Vector是采用數(shù)組方式存儲數(shù)據(jù),此數(shù)組元素總數(shù)大于實際存儲的數(shù)據(jù)個數(shù)以便增加和插入元素,二者都允許直接序號索引元素,但是插入數(shù)據(jù)要移動數(shù)組元素等內(nèi)存操作,所以它們索引數(shù)據(jù)快、插入數(shù)據(jù)慢。
Vector由于使用了synchronized同步方法(如add、insert、remove、set、equals、hashcode等操作),因此是線程安全,性能上比ArrayList要差。
LinkedList使用雙向鏈表實現(xiàn)存儲,按序號索引數(shù)據(jù)需要進(jìn)行向前或向后遍歷,但是插入數(shù)據(jù)時只需要記錄本項的前后項即可,所以插入數(shù)度較快!LinkedList雙向鏈表,是指可以從first依次遍歷至last(從頭到尾),也可以從last遍歷至first(從尾到頭),但首尾沒有構(gòu)成環(huán),不同于雙向循環(huán)鏈表(注意區(qū)分):
11、hashmap與hashtable的區(qū)別?
都屬于Map接口的類,實現(xiàn)了將惟一鍵映射到特定的值上。
HashMap類沒有分類或者排序。它允許一個null鍵和多個null值。
Hashtable類似于HashMap,但是不允許null鍵和null值。它也比HashMap慢,因為它是同步的。
12、Jsp有哪些內(nèi)置對象,作用分別是什么?(至少能說出五個)
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實例
13、Javaservletapi中forward()與redirect()的區(qū)別?
前者僅是容器中控制權(quán)的轉(zhuǎn)向,在客戶端瀏覽器地址欄中不會顯示出轉(zhuǎn)向后的地址;后者則是完全的跳轉(zhuǎn),瀏覽器將會得到跳轉(zhuǎn)的地址,并重新發(fā)送請求鏈接。這樣,從瀏覽器的地址欄中可以看到跳轉(zhuǎn)后的鏈接地址。所以,前者更加高效,在前者可以滿足需要時,盡量使用forward()方法,并且,這樣也有助于隱藏實際的鏈接。在有些情況下,比如,需要跳轉(zhuǎn)到一個其它服務(wù)器上的資源,則必須使用sendRedirect()方法。
14、重載(overload)與重寫(override)的區(qū)別?
Overload:方法名相同,參數(shù)不同,與返回值無關(guān)
Override:方法名相同,參數(shù)相同,相同的返回值,建立在繼承的基礎(chǔ)之上
15、什么是單例模式,在程序中如何使用?
單例模式確保一個類只有一個實例 餓漢式單例類
public class Singleton {
private Singleton(){}
private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}
}
懶漢式單例類
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance(){
if(instance==null)
instance=new Singleton();
return instance;
}
}
16、Servlet生命周期?
加載和實例化
初始化init()
請求處理service()
服務(wù)終止destroy()
17、spring中IOC與AOP的含義?
IOC:控制反轉(zhuǎn),是一種設(shè)計模式,一層含義控制權(quán)的轉(zhuǎn)移,由傳統(tǒng)的在程序中控制依賴轉(zhuǎn)移到由容器來控制,第二層是依賴注入將互相依賴的對象分離,在spring配置文件中描述它們的依賴關(guān)心,它們的依賴關(guān)系只是在使用的時候才建立
AOP:面向切面,是一種編程思想,oop的延續(xù),將系統(tǒng)中非核心的業(yè)務(wù)提取出來,進(jìn)行單獨(dú)的處理,比如事務(wù)、日志和安全等
Spring的AOP和IOC都是為了解決系統(tǒng)代碼耦合度過高的問題,使用代碼重用性高,易于維護(hù),不過AOP和IOC并不是spring中特有的,只是spring把它們應(yīng)用的更靈活方便。
18、hibernate與JDBC的區(qū)別?
相同點(diǎn):
1>兩者都是JAVA的數(shù)據(jù)庫操作中間件。
2>兩者對于數(shù)據(jù)庫進(jìn)行直接操作的對象都不是線程安全的,都需要及時關(guān)閉。
3>兩者都可以對數(shù)據(jù)庫的更新操作進(jìn)行顯式的事務(wù)處理。
不同點(diǎn):
1>使用的SQL語言不同:JDBC使用的是基于關(guān)系型數(shù)據(jù)庫的標(biāo)準(zhǔn)SQL語言,Hibernate使用的是HQL(Hibernate query language)語言
2>操作的對象不同:JDBC操作的是數(shù)據(jù),將數(shù)據(jù)通過SQL語句直接傳送到數(shù)據(jù)庫中執(zhí)行,Hibernate操作的是持久化對象,由底層持久化對象的數(shù)據(jù)更新到數(shù)據(jù)庫中。3>數(shù)據(jù)狀態(tài)不同:JDBC操作的數(shù)據(jù)是“瞬時”的,變量的值無法與數(shù)據(jù)庫中的值保持一致,而Hibernate操作的數(shù)據(jù)是可持久的,即持久化對象的數(shù)據(jù)屬性的值是可以跟數(shù)據(jù)庫中的值保持一致的。
19、struts中的標(biāo)簽庫有幾種,分別是?
有5種標(biāo)簽,分別是:bean標(biāo)簽庫、html標(biāo)簽庫、logic標(biāo)簽庫、tiles標(biāo)簽庫nested標(biāo)簽庫
20、Error與Exception有什么區(qū)別?
Error表示系統(tǒng)級的錯誤和程序不必處理的異常,Exception表示需要捕捉或者需要程序進(jìn)行處理的異常。
21、Collection和Collections的區(qū)別。
Collection是集合類的上級接口,繼承與他的接口主要有Set 和List.Collections是針對集合類的一個幫助類,他提供一系列靜態(tài)方法實現(xiàn)對各種集合的搜索、排序、線程安全化等操作
22、GC是什么?為什么要有GC?(基礎(chǔ))。
GC是垃圾收集器。Java程序員不用擔(dān)心內(nèi)存管理,因為垃圾收集器會自動進(jìn)行管理。
要請求垃圾收集,可以調(diào)用下面的方法之一:
System.gc()
Runtime.getRuntime().gc()
23、啟動一個線程是用run()還是start()?
啟動一個線程是調(diào)用start()方法,使線程所代表的虛擬處理機(jī)處于可運(yùn)行狀態(tài),這意味著它可以由JVM調(diào)度并執(zhí)行。這并不意味著線程就會立即運(yùn)行。run()方法可以產(chǎn)生必須退出的標(biāo)志來停止一個線程。
24、&和&&的區(qū)別。
&是位運(yùn)算符,表示按位與運(yùn)算,&&是邏輯運(yùn)算符,表示邏輯與(and)。
25、heap和stack有什么區(qū)別。
棧是一種線形集合,其添加和刪除元素的操作應(yīng)在同一段完成。棧按照后進(jìn)先出的方
式進(jìn)行處理。
堆是棧的一個組成元素
26、List, Set, Map是否繼承自Collection接口?
List,Set是,Map不是
27、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)行交互和重用。
28、Static Nested Class 和 Inner Class的不同。
Static Nested Class是被聲明為靜態(tài)(static)的內(nèi)部類,它可以不依賴于外部類實例被實例化。而通常的內(nèi)部類需要在外部類實例化后才能實例化。
29、接口是否可繼承接口? 抽象類是否可實現(xiàn)(implements)接口? 抽象類是否可繼承實體類
(concrete class)?
接口可以繼承接口。抽象類可以實現(xiàn)(implements)接口,抽象類是否可繼承實體類,但前提是實體類必須有明確的構(gòu)造函數(shù)
30、JSP和Servlet有哪些相同點(diǎn)和不同點(diǎn),他們之間的聯(lián)系是什么?
JSP 是Servlet技術(shù)的擴(kuò)展,本質(zhì)上是Servlet的簡易方式,更強(qiáng)調(diào)應(yīng)用的外表表達(dá)。JSP編譯后是“類servlet”。Servlet和JSP最主要的不同點(diǎn)在于,Servlet的應(yīng)用邏輯是在Java文件中,并且完全從表示層中的HTML里分離開來。而JSP的情況是Java和HTML可以組合成一個擴(kuò)展名為.jsp的文件。JSP側(cè)重于視圖,Servlet主要用于控制邏輯
31、當(dāng)一個線程進(jìn)入一個對象的一個synchronized方法后,其它線程是否可進(jìn)入此對象的其它方法? 不能,一個對象的一個synchronized方法只能由一個線程訪問。
32、運(yùn)行時異常與一般異常有何異同?
異常表示程序運(yùn)行過程中可能出現(xiàn)的非正常狀態(tài),運(yùn)行時異常表示虛擬機(jī)的通常操作中可能遇到的異常,是一種常見運(yùn)行錯誤。java編譯器要求方法必須聲明拋出可能發(fā)生的非運(yùn)行時異常,但是并不要求必須聲明拋出未被捕獲的運(yùn)行時異常。
33、JSP中動態(tài)INCLUDE與靜態(tài)INCLUDE的區(qū)別?
動態(tài)INCLUDE用jsp:include動作實現(xiàn)
靜態(tài)INCLUDE用include偽碼實現(xiàn),定不會檢查所含文件的變化,適用于包含靜態(tài)頁面<%@ include file=“included.htm” %>
第四篇:java程序員面試題
1、你怎樣理解Struts,又那些配置文件,以及作用? 理解:http://ruixin.iteye.com/blog/899289 配置文件:struts.xml 作用:struts 框架mvc 實現(xiàn)低耦合,便于程序的維護(hù)~ 配置文件控制流程的轉(zhuǎn)向 很清晰~ 主要負(fù)責(zé)具體業(yè)務(wù)的實現(xiàn)和頁面的轉(zhuǎn)向~
2、怎么樣來捕獲數(shù)據(jù)庫中的異常?
3、如何處理網(wǎng)頁中的驗證信息,如何友好的進(jìn)行處理?
4、用javaScript實現(xiàn)java中的監(jiān)聽器功能?
5、你對對日外包的看法?
6、數(shù)據(jù)庫連接方式由哪幾種?
Jdbc、連接池、hibernate
7、你清楚哪幾種設(shè)計模式,談?wù)劯鞣N設(shè)計模式的類結(jié)構(gòu)。
8、談?wù)刯sp和sevlet的區(qū)別,以及它們性能上的區(qū)別。
jsp是servlet的一種簡化,jsp編譯后是“類servlet”。servlet 主要是用來處理業(yè)務(wù)層;
jsp 則是主要負(fù)責(zé) 表現(xiàn)層。
servlet完全是java程序代碼構(gòu)成,擅長于流程控制和事務(wù)處理,而通過servlet來生成動態(tài)網(wǎng)頁很不直觀; 對于靜態(tài)的html標(biāo)簽,servlet都必須使用頁面輸出流逐行輸出。Servlet中沒有內(nèi)置對象。Jsp由html代碼和jsp標(biāo)簽構(gòu)成可以方便地編寫動態(tài)網(wǎng)頁,在struts框架中,jsp位于MVC設(shè)計模式的視圖層,而servlet位于控制層。
總之,使用jsp只需要完成程序員需要輸出到客戶端的內(nèi)容,至于jsp中的java腳本如果鑲嵌到一個類中,由jsp容器完成,而servlet則是個完整的java類,這個類的service方法用于生成對客戶端的響應(yīng)
9、如何來編寫存儲過程,如何優(yōu)化存儲過程,以及存儲過程和TSQL的區(qū)別。
10、提供的培訓(xùn),CMM-5軟件開發(fā)流程培訓(xùn)、代碼編寫規(guī)范和業(yè)務(wù)流程培訓(xùn)、對日語的培訓(xùn)。
1、為什么要選擇這個行業(yè),和計算機(jī)專業(yè)的相比有什么優(yōu)勢?
2、Servlet是什么,以及生命周期?
Servlet被服務(wù)器實例化后,容器運(yùn)行其init方法,請求到達(dá)時運(yùn)行其service方法,service方法自動派遣運(yùn)行與請求對應(yīng)的doXXX方法(doGet,doPost)等,當(dāng)服務(wù)器決定將實例銷毀的時候調(diào)用其destroy方法。
與cgi的區(qū)別在于servlet處于服務(wù)器進(jìn)程中,它通過多線程方式運(yùn)行其service方法,一個實例可以服務(wù)于多個請求,并且其實例一般不會銷毀,而CGI對每個請求都產(chǎn)生新的進(jìn)程,服務(wù)完成后就銷毀,所以效率上低于servlet。
3、怎么理解事務(wù)?
4、怎么理解MVC?
自己做自己的事情,主要強(qiáng)調(diào)分層,5、同時插入大量數(shù)據(jù),使用何種方法優(yōu)化?Batch
6、多個有關(guān)系得怎么樣操作?
7、你認(rèn)為你還有什么優(yōu)點(diǎn)在前面沒有提到?
8、對加班的看法?
9、與上級意見不一致時怎么樣處理?10、11、12、13、14、15、16、17、18、19、20、21、22、23、你如何理解團(tuán)隊精神?
你怎樣處理學(xué)習(xí)新技術(shù)和項目開發(fā)之間的矛盾? 怎樣去學(xué)習(xí)新技術(shù)?
作為一個初級程序員怎么樣彌補(bǔ)與有經(jīng)驗程序員之間的差距? 你對索引的理解,索引有幾種,什么時候用索引? 對Oracle理解?
怎樣優(yōu)化復(fù)雜的查詢語句? 你對Jdbc理解?
對Finally塊的理解和應(yīng)用? 游標(biāo)的理解? ResultSet 重載,重寫? 簽名
EJB的事務(wù),Hibernate的事務(wù)? Struts的標(biāo)簽? 重定向和跳轉(zhuǎn)? A、
a.地址欄不改變跳轉(zhuǎn)——服務(wù)器端跳轉(zhuǎn),服務(wù)器之間內(nèi)部轉(zhuǎn),相同的request,可傳參;
b.執(zhí)行到跳轉(zhuǎn)語句后無條件立刻跳轉(zhuǎn)——之后的代碼不再被執(zhí)行;
注意:如果使用forward跳轉(zhuǎn),則一定要在跳轉(zhuǎn)之前釋放掉全部的資源;
c.使用forward時,request設(shè)置的屬性依然能保留在下一個頁面(setAttribute);d.通過
e.地址中的”/”代表是:http://localhost:8080/Test B、response.sendRedirect(“地址”):效率低,速度慢
a.地址欄改變跳轉(zhuǎn)——客戶端跳轉(zhuǎn)(其中地址可以是任意的)
b.所有代碼執(zhí)行完畢之后再跳轉(zhuǎn),跳轉(zhuǎn)語句后面的代碼還是會執(zhí)行,除非在其后面加上return(return)需復(fù)雜一些。
<% Response.sendRedirect(“aa.jsp”);boolean b = true;
if(b){ Return;} System.out.println(“aaaaaaaaaa”);%>
c.不能保存request屬性——地址改變了,客戶端跳轉(zhuǎn),不同的request d.通過對URL地址的重寫傳遞參數(shù):
response.sendRedirect(“responseDemo04.jsp?id=mldn”);
e.地址中的”/”代表是:http://localhost:8080/
下面是兩種比較重要的跳轉(zhuǎn),我還是與上次的一次,把我做的筆記貼出來:24、25、Hibernate的左聯(lián)結(jié)和右連接,緩存,數(shù)據(jù)加載? 面向?qū)ο笕绾卫斫?
26、EJB中CMP和BMP,SessionBean的機(jī)制?27、28、29、對日外包是否有抵觸情緒? 如何減少Servlet的請求? 對設(shè)計模式了解多少?作過的項目中用過那些設(shè)計模式? 30、31、32、33、34、35、36、37、38、39、40、41、42、43、44、45、怎樣看待團(tuán)隊合作,在團(tuán)隊合作中你扮演什么樣的角色,遇到技術(shù)難題時怎么解決? Exception的層次結(jié)構(gòu)? EJB對數(shù)據(jù)庫的訪問機(jī)制? Struts中是否有事務(wù)處理? Hibernate的其它功能(除了ORM)? 如何提高數(shù)據(jù)庫中的數(shù)據(jù)查詢效率? 作為項目經(jīng)理如何對組內(nèi)成員分工? 描述一下你做過項目的流程。
加班到12點(diǎn),突然有人來問你技術(shù)上的難題,你會如何處理? Oracle的冷備份、熱備份 Strurs中怎樣實現(xiàn) Hibernate怎樣實現(xiàn)ORM Spring 的事務(wù)處理機(jī)制
Strurs的驗證方式,Javascript的驗證的方式
一個是服務(wù)器端驗證,一個是客戶端驗證
Struts的工作機(jī)制 Delete/trancate的區(qū)別
trancate與delete都是刪除數(shù)據(jù),不同的是trancate是將表的所有數(shù)據(jù)都刪除,而delete可以有選擇地刪除數(shù)據(jù); delete刪除數(shù)據(jù)是記錄在日志中的,可以通過其將數(shù)據(jù)恢復(fù),而trancate則是將整個表截斷,其操作是不記錄在日志里的。46、47、48、作為項目組長,你遇到的最大問題是什么?如何解決?
Ajax/內(nèi)嵌框架實現(xiàn)局部刷新,有什么差別?
Exception/Error的區(qū)別,在什么情況下可以拋出RuntimeException 父類不同
知道異常和錯誤最本質(zhì)的區(qū)別就是異常能被開發(fā)人員處理而錯誤時系統(tǒng)本來自帶的,一般無法處理也不需要我們程序員來處理。
在程序運(yùn)行時候出錯而又不是系統(tǒng)原因差生的,一般是由于程序原因產(chǎn)生,比如程序?qū)懙牟粔驀?yán)謹(jǐn)、完善
典型的RuntimeException
有
ArithmeticException、ClassCastException、IndexOutOfBoundsException、NullPointerException、UnsupportedOperationException 等.49、50、51、52、53、54、55、56、57、58、59、Orcale 物化視圖(MV)
業(yè)務(wù)處理模塊中,是如何處理事務(wù)? Sql語句如何優(yōu)化 數(shù)據(jù)庫右連接
JDBC的連接關(guān)閉在哪?
Finally語句塊內(nèi)
錯誤處理模塊是放在哪個層的。接口能否繼承接口。
接口可以繼承接口..但是要使用extends~而不是用implements 抽象類能否繼承實體類。
抽象類是可以繼承實體類,但前提是實體類必須有明確的構(gòu)造函數(shù) 答案很明確,可以繼承。
項目中查詢時怎么樣實現(xiàn)的?
作為項目負(fù)責(zé)人你是管理這個團(tuán)隊的?
在你做項目過程中遇到些什么問題,是怎么樣解決的?
Jquery中的幾種選擇器:
Javascript如何進(jìn)行數(shù)字和字符串之間的轉(zhuǎn)換?
數(shù)字類型轉(zhuǎn)換成String類型用 對象=對象.toString()方法,字符串轉(zhuǎn)換成數(shù)字類型則是對象=Number(對象);
第五篇:Java就業(yè)面試題
1、一個“.java”源文件中是否可以包括多個類(不是內(nèi)部類)?有什么限制? 可以有多個類,但只能有一個public的類,并且public的類名必須與文件名相一致。
3、說說&和&&的區(qū)別。
&和&&都可以用作邏輯與的運(yùn)算符,表示邏輯與(and),當(dāng)運(yùn)算符兩邊的表達(dá)式的結(jié)果都為true時,整個運(yùn)算結(jié)果才為true,否則,只要有一方為false,則結(jié)果為false。
&&還具有短路的功能,即如果
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。
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ū)別?
==操作符專門用來比較兩個變量的值是否相等,也就是用于比較變量所對應(yīng)的內(nèi)存中所存儲的數(shù)值是否相同,要比較兩個基本類型的數(shù)據(jù)或兩個引用變量是否相等,只能用==操作符。
equals方法是用于比較兩個獨(dú)立對象的內(nèi)容是否相同,就好比去比較兩個人的長相是否相同,它比較的兩個對象是獨(dú)立的。例如,對于下面的代碼:
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)變量則可以直接使用類名來引用。
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)用。一個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.floor(11.6)的結(jié)果為11,Math.floor(-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。
15、下面的代碼有什么不妥之處? 1.if(username.equals(“zxx”){} 如果username=null;會報異常,而且少個括號結(jié)束。
2.int x = 1;return x==1?true:false;X==1返回的本來就是boolean類型 后面的true:false是多余的.16、請說出作用域public,private,protected,以及不寫時的區(qū)別 這四個作用域的可見范圍如下表所示。
說明:如果在修飾的元素上面沒有寫任何訪問修飾符,則表示friendly。
作用域
當(dāng)前類 同一package 子孫類 其他package public
√
√
√
√ protected √
√
√
× friendly
√
√
×
× private
√
×
×
×
備注:只要記住了有4種訪問權(quán)限,4個訪問范圍,然后將全選和范圍在水平和垂直方向上分別按排從小到大或從大到小的順序排列,就很容易畫出上面的圖了。
17、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)接口聲明的所有方法。除了這個典型的用法以外,我們在繼承中也可能會在子類覆蓋父類中的方法。在覆蓋要注意以下的幾點(diǎn):
1、覆蓋的方法的標(biāo)志必須要和被覆蓋的方法的標(biāo)志完全匹配,才能達(dá)到覆蓋的效果;
2、覆蓋的方法的返回值必須和被覆蓋的方法的返回一致;
3、覆蓋的方法所拋出的異常必須和被覆蓋方法的所拋出的異常一致,或者是其子類;
4、被覆蓋的方法不能為private,否則在其子類中只是新定義了一個方法,并沒有對其進(jìn)行覆蓋。
overload對我們來說可能比較熟悉,可以翻譯為重載,它是指我們可以定義一些名稱相同的方法,通過定義不同的輸入?yún)?shù)來區(qū)分這些方法,然后再調(diào)用時,VM就會根據(jù)不同的參數(shù)樣式,來選擇合適的方法執(zhí)行。在使用重載要注意以下的幾點(diǎn):
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á)到重載的效果。
18、說說對javaee中的session的理解,你是怎么用session的?
在Java Servlet API中引入session機(jī)制來跟蹤客戶的狀態(tài)。session指的是在一段時間內(nèi),單個客戶與Web服務(wù)器的一連串相關(guān)的交互過程。在一個session中,客戶可能會多次請求同一個網(wǎng)頁,也有可能請求訪問各種不同的服務(wù)器資源。例如在電子郵件應(yīng)用中,從一個客戶登錄到電子郵件系統(tǒng)開始,經(jīng)過收信,寫信,和發(fā)信等,直至退出郵件系統(tǒng),整個過程為一個session。再比如,在網(wǎng)上書店應(yīng)用中,從一個客戶開始購物,到最后結(jié)賬,整個過程為一個session。
會話的創(chuàng)建:HttpSession session = request.getSession(boolean value);HttpSession session = request.getSession();會話的使用:javax.servlet.http.HttpSession接口中定義的方法,我們常用的是有關(guān)進(jìn)行數(shù)據(jù)存取的方法。
session.setAttribute(String name , Object value);session.getAttribute(String name);
19、說說has a與is a的區(qū)別。
is-a表示的是屬于得關(guān)系。比如兔子屬于一種動物(繼承關(guān)系)。has-a表示組合,包含關(guān)系。比如兔子包含有腿,頭等組件;
20、線程如何同步和通訊。
只有多個synchronized代碼塊使用的是同一個監(jiān)視器對象,這些synchronized代碼塊之間才具有線程互斥的效果,假如a代碼塊用obj1作為監(jiān)視器對象,假如b代碼塊用obj2作為監(jiān)視器對象,那么,兩個并發(fā)的線程可以同時分別進(jìn)入這兩個代碼塊中。對于同步方法的分析,所用的同步監(jiān)視器對象是this 接著對于靜態(tài)同步方法的分析,所用的同步監(jiān)視器對象是該類的Class對象 接著對如何實現(xiàn)代碼塊與方法的同步進(jìn)行分析。2.ClassLoader如何加載class。
jvm里有多個類加載,每個類加載可以負(fù)責(zé)加載特定位置的類,例如,bootstrap類加載負(fù)責(zé)加載jre/lib/rt.jar中的類,我們平時用的jdk中的類都位于rt.jar中。
extclassloader負(fù)責(zé)加載jar/lib/ext/*.jar中的類,appclassloader負(fù)責(zé)classpath指定的目錄或jar中的類。除了bootstrap之外,其他的類加載器本身也都是java類,它們的父類是ClassLoader。3.Servlet的生命周期
? 通常情況下,服務(wù)器只會創(chuàng)建一個Servlet實例對象,也就是說Servlet實例對象一旦創(chuàng)建,它就會駐留在內(nèi)存中,為后續(xù)的其它請求服務(wù),直至web容器退出,servlet實例對象才會銷毀。
Web容器退出,調(diào)用destory方法,結(jié)束servlet; 4.抽象類的作用
5.ArrayList如何實現(xiàn)插入的數(shù)據(jù)按自定義的方式有序存放 class MyBean implements Comparable{ public int compareTo(Object obj){ if(!obj instanceof MyBean)throw new ClassCastException()//具體異常的名稱,我要查jdk文檔。
MyBean other =(MyBean)obj;return age > other.age?1:age== other.age?0:-1;} }
class MyTreeSet {
private ArrayList datas = new ArrayList();
public void add(Object obj){ for(int i=0;i 6.分層設(shè)計的好處;把各個功能按調(diào)用流程進(jìn)行了模塊化,模塊化帶來的好處就是可以隨意組合,舉例說明:如果要注冊一個用戶,流程為顯示界面并通過界面接收用戶的輸入,接著進(jìn)行業(yè)務(wù)邏輯處理,在處理業(yè)務(wù)邏輯又訪問數(shù)據(jù)庫,如果我們將這些步驟全部按流水帳的方式放在一個方法中編寫,這也是可以的,但這其中的壞處就是,當(dāng)界面要修改時,由于代碼全在一個方法內(nèi),可能會碰壞業(yè)務(wù)邏輯和數(shù)據(jù)庫訪問的碼,同樣,當(dāng)修改業(yè)務(wù)邏輯或數(shù)據(jù)庫訪問的代碼時,也會碰壞其他部分的代碼。分層就是要把界面部分、業(yè)務(wù)邏輯部分、數(shù)據(jù)庫訪問部分的代碼放在各自獨(dú)立的方法或類中編寫,這樣就不會出現(xiàn)牽一發(fā)而動全身的問題了。這樣分層后,還可以方便切換各層,譬如原來的界面是Swing,現(xiàn)在要改成 BS界面,如果最初是按分層設(shè)計的,這時候不需要涉及業(yè)務(wù)和數(shù)據(jù)訪問的代碼,只需編寫一條web界面就可以了。 下面的僅供參考,不建議照搬照套,一定要改成自己的語言,發(fā)現(xiàn)內(nèi)心的感受: 分層的好處: 1,實現(xiàn)了軟件之間的解耦; 2.便于進(jìn)行分工 3.便于維護(hù) 4,提高軟件組件的重用 5.便于替換某種產(chǎn)品,比如持久層用的是hibernate,需要更換產(chǎn)品用toplink,就不用該其他業(yè)務(wù)代碼,直接把配置一改。6.便于產(chǎn)品功能的擴(kuò)展。 7。便于適用用戶需求的不斷變化 7.序列化接口的id有什么用? 對象經(jīng)常要通過IO進(jìn)行傳送,讓你寫程序傳遞對象,你會怎么做?把對象的狀態(tài)數(shù)據(jù)用某種格式寫入到硬盤,Person->“zxx,male,28,30000”?Person,既然大家都要這么干,并且沒有個統(tǒng)一的干法,于是,sun公司就提出一種統(tǒng)一的解決方案,它會把對象變成某個格式進(jìn)行輸入和輸出,這種格式對程序員來說是透明(transparent)的,但是,我們的某個類要想能被sun的這種方案處理,必須實現(xiàn)Serializable接口。 ObjectOutputStream.writeObject(obj);Object obj = ObjectInputStream.readObject();假設(shè)兩年前我保存了某個類的一個對象,這兩年來,我修改該類,刪除了某個屬性和增加了另外一個屬性,兩年后,我又去讀取那個保存的對象,或有什么結(jié)果?未知!sun的jdk就會蒙了。為此,一個解決辦法就是在類中增加版本后,每一次類的屬性修改,都應(yīng)該把版本號升級一下,這樣,在讀取時,比較存儲對象時的版本號與當(dāng)前類的版本號,如果不一致,則直接報版本號不同的錯! 9.hashCode方法的作用?說(網(wǎng)友提供的一段,待改進(jìn):hashcode這個方法是用來鑒定2個對象是否相等的。 那你會說,不是還有equals這個方法嗎? 不錯,這2個方法都是用來判斷2個對象是否相等的。但是他們是有區(qū)別的。一般來講,equals這個方法是給用戶調(diào)用的,如果你想判斷2個對象是否相等,你可以重寫equals方法,然后在代碼中調(diào)用,就可以判斷他們是否相等了。簡單來講,equals方法主要是用來判斷從表面上看或者從內(nèi)容上看,2個對象是不是相等。舉個例子,有個學(xué)生類,屬性只有姓名和性別,那么我們可以認(rèn)為只要姓名和性別相等,那么就說這2個對象是相等的。 hashcode方法一般用戶不會去調(diào)用,比如在hashmap中,由于key是不可以重復(fù)的,他在判斷key是不是重復(fù)的時候就判斷了hashcode這個方法,而且也用到了equals方法。這里不可以重復(fù)是說equals和hashcode只要有一個不等就可以了!所以簡單來講,hashcode相當(dāng)于是一個對象的編碼,就好像文件中的md5,他和equals不同就在于他返回的是int型的,比較起來不直觀。我們一般在覆蓋equals的同時也要覆蓋hashcode,讓他們的邏輯一致。舉個 例子,還是剛剛的例子,如果姓名和性別相等就算2個對象相等的話,那么hashcode的方法也要返回姓名的hashcode值加上性別的hashcode值,這樣從邏輯上,他們就一致了。 要從物理上判斷2個對象是否相等,用==就可以了。) 10.webservice問得很多 11.設(shè)計出計算任意正整數(shù)的階層。 4.在oracle數(shù)據(jù)庫中需要查詢出前8條記錄的sql語句怎么寫? Select * from(select *,rownum r from test where r<8) 5.什么是SOA,談?wù)勀愕腟OA的理解。service orientied architecture 面向服務(wù)的體系結(jié)構(gòu)(Service-Oriented Architecture,SOA)是一個組件模型,它將應(yīng)用程序的不同功能單元(稱為服務(wù))通過這些服務(wù)之間定義良好的接口和契約聯(lián)系起來。接口是采用中立的方式進(jìn)行定義的,它應(yīng)該獨(dú)立于實現(xiàn)服務(wù)的硬件平臺、操作系統(tǒng)和編程語言。這使得構(gòu)建在各種這樣的系統(tǒng)中的服務(wù)可以一種統(tǒng)一和通用的方式進(jìn)行交互。松耦合的 6.如何實現(xiàn)線程間的通訊。 新題目:編程:1.編寫一個函數(shù)將一個十六進(jìn)制數(shù)的字符串參數(shù)轉(zhuǎn)換成整數(shù)返回。String str = “13abf”;int len = str.length;int sum = 0;for(int i=0;i 其實,也可以用Integer.parseInt(str,16),但面試官很可能是想考我們的編碼基本功。 編程2 :銀行貸款的還款方式中最常用的是一種叫“等額本息”,還款法,即借款人在約定還款期限內(nèi)的每一期(月)歸還的金額(產(chǎn)生的利息+部分本金)都是相等的,現(xiàn)有一筆總額為T元的N年期住房貸款,年利率為R,要求算出每一期的還款的本金和利息總額,請寫出解決思路和任意一種編程語言實現(xiàn)的主要代碼。思路:既然是按月還款,那我就要將N年按月來計算,即要還N*12個月,這樣就可以求出每月要還的本金。由于每月要還的那部分本金所欠的時間不同,所以, 它們所產(chǎn)生的利息是不同的,該部分本金的利息為:部分本金額*所欠月數(shù)*月利率。應(yīng)該是這么個算法,如果利息還計利息,如果月還款不按年利率來算,老百姓算不明白的。 int monthMoney = T/N/12;float monthRate = R/12;int totalMonth = N * 12;float totalRate = 0;for(int i=1;i<=totalMonth;i++){ totalRate += monthMoney * monthRate * i;} int result = monthMoney + totalRate/N/12; 幾道題: 1.****Spring的DI是什么(學(xué)員注:除了IOC,AOP這些概念,還不太清楚DI的概念) 什么是DI機(jī)制? 依賴注入(Dependecy Injection)和控制反轉(zhuǎn)(Inversion of Control)是同一個概念,具體的講:當(dāng)某個角色 需要另外一個角色協(xié)助的時候,在傳統(tǒng)的程序設(shè)計過程中,通常由調(diào)用者來創(chuàng)建被調(diào)用者的實例。但在spring中 創(chuàng)建被調(diào)用者的工作不再由調(diào)用者來完成,因此稱為控制反轉(zhuǎn)。創(chuàng)建被調(diào)用者的工作由spring來完成,然后注入調(diào)用者 因此也稱為依賴注入。 spring以動態(tài)靈活的方式來管理對象,注入的兩種方式,設(shè)置注入和構(gòu)造注入。 設(shè)置注入的優(yōu)點(diǎn):直觀,自然 構(gòu)造注入的優(yōu)點(diǎn):可以在構(gòu)造器中決定依賴關(guān)系的順序。 2.*任意數(shù)字序列“123456”之類,輸出它們所有的排列組合 2題的答案: String str = “xafdvs”;char[] arr1 = str.toCharArray();char[] arr2 = Arrays.copyOf(arr1,arr1.length);for(int i=0;i 3.*****什么是AOP(學(xué)員注:會用,但感覺說不清楚)什么是AOP? 面向切面編程(AOP)完善spring的依賴注入(DI),面向切面編程在spring中主要表現(xiàn)為兩個方面 1.面向切面編程提供聲明式事務(wù)管理 2.spring支持用戶自定義的切面 面向切面編程(aop)是對面向?qū)ο缶幊蹋╫op)的補(bǔ)充,面向?qū)ο缶幊虒⒊绦蚍纸獬筛鱾€層次的對象,面向切面編程將程序運(yùn)行過程分解成各個切面。 AOP從程序運(yùn)行角度考慮程序的結(jié)構(gòu),提取業(yè)務(wù)處理過程的切面,oop是靜態(tài)的抽象,aop是動態(tài)的抽象,是對應(yīng)用執(zhí)行過程中的步驟進(jìn)行抽象,從而獲得步驟之間的邏輯劃分。 aop框架具有的兩個特征: 1.各個步驟之間的良好隔離性 2.源代碼無關(guān)性 spring 的優(yōu)點(diǎn)? 1.降低了組件之間的耦合性,實現(xiàn)了軟件各層之間的解耦 2.可以使用容易提供的眾多服務(wù),如事務(wù)管理,消息服務(wù)等 3.容器提供單例模式支持 4.容器提供了AOP技術(shù),利用它很容易實現(xiàn)如權(quán)限攔截,運(yùn)行期監(jiān)控等功能 5.容器提供了眾多的輔助類,能加快應(yīng)用的開發(fā) 6.spring對于主流的應(yīng)用框架提供了集成支持,如hibernate,JPA,Struts等 7.spring屬于低侵入式設(shè)計,代碼的污染極低 8.獨(dú)立于各種應(yīng)用服務(wù)器 9.spring的DI機(jī)制降低了業(yè)務(wù)對象替換的復(fù)雜性 10.Spring的高度開放性,并不強(qiáng)制應(yīng)用完全依賴于Spring,開發(fā)者可以自由選擇spring的部分或全部 3題的答案: 1.概念介紹:所謂AOP,即Aspect orientied program,就是面向方面的編程,2.解釋什么是方面:貫穿到系統(tǒng)的各個模塊中的系統(tǒng)一個功能就是一個方面,比如,記錄日志,統(tǒng)一異常處理,事務(wù)處理,全限檢查,這些功能都是軟件系統(tǒng) 的一個面,而不是一點(diǎn),在各個模塊中都要出現(xiàn)。 3.什么是面向方面編程:把系統(tǒng)的一個方面的功能封裝成對象的形式來處理 4.怎么進(jìn)行面向方面編程:把功能模塊對應(yīng)的對象作為切面嵌入到原來的各個系統(tǒng)模塊中,采用代理技術(shù),代理會調(diào)用目標(biāo),同時把切面功能的代碼(對象)加入進(jìn)來,所以,用spring配置代理對象時只要要配兩個屬性,分別表示目標(biāo)和切面對象(Advisor)。 3、構(gòu)造器Constructor是否可被override? 構(gòu)造器Constructor不能被繼承,因此不能重寫Override,但可以被重載Overload。 4、接口是否可繼承接口? 抽象類是否可實現(xiàn)(implements)接口? 抽象類是否可繼承具體類(concrete class)? 抽象類中是否可以有靜態(tài)的main方法? 接口可以繼承接口。抽象類可以實現(xiàn)(implements)接口,抽象類可繼承具體類。抽象類中可以有靜態(tài)的main方法。 備注:只要明白了接口和抽象類的本質(zhì)和作用,這些問題都很好回答,你想想,如果你是java語言的設(shè)計者,你是否會提供這樣的支持,如果不提供的話,有什么理由嗎?如果你沒有道理不提供,那答案就是肯定的了。 只有記住抽象類與普通類的唯一區(qū)別就是不能創(chuàng)建實例對象和允許有abstract方法。 5、寫clone()方法時,通常都有一行代碼,是什么? clone 有缺省行為,super.clone();因為首先要把父類中的成員復(fù)制到位,然后才是復(fù)制自己的成員。 6、面向?qū)ο蟮奶卣饔心男┓矫?/p> 計算機(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言有封裝、繼承、抽象、多態(tài)等4個主要的特征。1封裝: 封裝是保證軟件部件具有優(yōu)良的模塊性的基礎(chǔ),封裝的目標(biāo)就是要實現(xiàn)軟件部件的“高內(nèi)聚、低耦合”,防止程序相互依賴性而帶來的變動影響。在面向?qū)ο蟮木幊陶Z言中,對象是封裝的最基本單位,面向?qū)ο蟮姆庋b比傳統(tǒng)語言的封裝更為清晰、更為有力。面向?qū)ο蟮姆庋b就是把描述一個對象的屬性和行為的代碼封裝在一個“模塊”中,也就是一個類中,屬性用變量定義,行為用方法進(jìn)行定義,方法可以直接訪問同一個對象中的屬性。通常情況下,只要記住讓變量和訪問這個變量的方法放在一起,將一個類中的成員變量全部定義成私有的,只有這個類自己的方法才可以訪問到這些成員變量,這就基本上實現(xiàn)對象的封裝,就很容易找出要分配到這個類上的方法了,就基本上算是會面向?qū)ο蟮木幊塘?。把握一個原則:把對同一事物進(jìn)行操作的方法和相關(guān)的方法放在同一個類中,把方法和它操作的數(shù)據(jù)放在同一個類中。 例如,人要在黑板上畫圓,這一共涉及三個對象:人、黑板、圓,畫圓的方法要分配給哪個對象呢?由于畫圓需要使用到圓心和半徑,圓心和半徑顯然是圓的屬性,如果將它們在類中定義成了私有的成員變量,那么,畫圓的方法必須分配給圓,它才能訪問到圓心和半徑這兩個屬性,人以后只是調(diào)用圓的畫圓方法、表示給圓發(fā)給消息而已,畫圓這個方法不應(yīng)該分配在人這個對象上,這就是面向 對象的封裝性,即將對象封裝成一個高度自治和相對封閉的個體,對象狀態(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); 比喻:人吃飯,你看到的是左手,還是右手? 7、java中實現(xiàn)多態(tài)的機(jī)制是什么? 靠的是父類或接口定義的引用變量可以指向子類或具體實現(xiàn)類的實例對象,而程序調(diào)用的方法在運(yùn)行期才動態(tài)綁定,就是引用變量所指向的具體實例對象的方法,也就是內(nèi)存里正在運(yùn)行的那個對象的方法,而不是引用變量的類型中定義的方法。 8、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 class BaseServlet 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 extends BaseServlet { protected void doService(HttpServletRequest request, HttpServletResponse response)throws IOExcetion,ServletException { 本Servlet只處理的具體業(yè)務(wù)邏輯代碼 } } 父類方法中間的某段代碼不確定,留給子類干,就用模板方法設(shè)計模式。備注:這道題的思路是先從總體解釋抽象類和接口的基本概念,然后再比較兩者的語法細(xì)節(jié),最后再說兩者的應(yīng)用區(qū)別。比較兩者語法細(xì)節(jié)區(qū)別的條理是:先從一個類中的構(gòu)造方法、普通成員變量和方法(包括抽象方法),靜態(tài)變量和方法,繼承性等6個方面逐一去比較回答,接著從 9、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(String name)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是什么。 10、什么是內(nèi)部類?Static Nested Class 和 Inner Class的不同。 內(nèi)部類就是在一個類的內(nèi)部定義的類,內(nèi)部類中不能定義靜態(tài)成員(靜態(tài)成員不是對象的特性,只是為了找一個容身之處,所以需要放到一個類中而已,這么一點(diǎn)小事,你還要把它放到類內(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成員變量。當(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)部類的總體方面的特點(diǎn):例如,在兩個地方可以定義,可以訪問外部類的成員變量,不能定義靜態(tài)成員,這是大的特點(diǎn)。然后再說一些細(xì)節(jié)方面的知識,例如,幾種定義方式的語法區(qū)別,靜態(tài)內(nèi)部類,以及匿名內(nèi)部類。 11、內(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)部類不能訪問外部類的成員,但你一上來就頂牛,這不好,要先順著人家,讓人家滿意,然后再說特殊情況,讓人家吃驚。 12、Anonymous Inner Class(匿名內(nèi)部類)是否可以extends(繼承)其它類,是否可以implements(實現(xiàn))interface(接口)? 可以繼承其他類或?qū)崿F(xiàn)其他接口。不僅是可以,而是必須! 13、super.getClass()方法調(diào)用 下面程序的輸出結(jié)果是多少? import java.util.Date;public class Test extends Date{ public static void main(String[] args){ new Test().test();} public void test(){ 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(); 14.jdk中哪些類是不能繼承的? 不能繼承的是類是那些用final關(guān)鍵字修飾的類。一般比較基本的類型或防止擴(kuò)展類無意間破壞原來方法的實現(xiàn)的類型都應(yīng)該是final的,在jdk中System,String,StringBuffer等都是基本類型。 2、String是最基本的數(shù)據(jù)類型嗎? 基本數(shù)據(jù)類型包括byte、int、char、long、float、double、boolean和short。java.lang.String類是final類型的,因此不可以繼承這個類、不能修改這個類。為了提高效率節(jié)省空間,我們應(yīng)該用StringBuffer類 111、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)點(diǎn),比如因為它的對象是只讀的,所以多線程并發(fā)訪問也不會有任何問題。當(dāng)然也有一些缺點(diǎn),比如每個不同的狀態(tài)都要一個對象來代表,可能會造成性能上的問題。所以Java標(biāo)準(zhǔn)類庫還提供了一個可變版本,即 StringBuffer。 41、是否可以繼承String類? String類是final類故不可以繼承。 27、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ū)拿。 5、String 和StringBuffer的區(qū)別 JAVA平臺提供了兩個類:String和StringBuffer,它們可以儲存和操作字符串,即包含多個字符的字符數(shù)據(jù)。String類表示內(nèi)容不可改變的字符串。而StringBuffer類表示內(nèi)容可以被修改的字符串。當(dāng)你知道字符數(shù)據(jù)要改變的時候你就可以使用StringBuffer。典型地,你可以使用StringBuffers來動態(tài)構(gòu)造字符數(shù)據(jù)。另外,String實現(xiàn)了equals方法,new String(“abc”).equals(new String(“abc”)的結(jié)果為true,而StringBuffer沒有實現(xiàn)equals方法,所以,new StringBuffer(“abc”).equals(new StringBuffer(“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)問題。 8.StringBuffer與StringBuilder的區(qū)別 StringBuffer和StringBuilder類都表示內(nèi)容可以被修改的字符串,StringBuilder是線程不安全的,運(yùn)行效率高,如果一個字符串變量是在方法里面定義,這種情況只可能有一個線程訪問它,不存在不安全的因素了,則用StringBuilder。如果要在類里面定義成員變量,并且這個類的實例對象會在多線程環(huán)境下使用,那么最好用StringBuffer。 3、如何把一段逗號分割的字符串轉(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();} 38、數(shù)組有沒有l(wèi)ength()這個方法? String有沒有l(wèi)ength()這個方法? 數(shù)組沒有l(wèi)ength()這個方法,有l(wèi)ength的屬性。String有有l(wèi)ength()這個方法。 39、下面這條語句一共創(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“); } 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)罐子里的。 7、下面的程序代碼輸出的結(jié)果是多少? public class smallT { public static void main(String args[]){ smallT t = new smallT();int b = t.get();System.out.println(b);} public int get(){ try { return 1;} finally { return 2;} } } 返回的結(jié)果是2。 我可以通過下面一個例子程序來幫助我解釋這個答案,從下面例子的運(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語句后才真正開始返回。在講解答案時可以用下面的程序來幫助分析: public class Test { /** * @param args add by zxx ,Dec 9, 2008 */ public static void main(String[] args){ // TODO Auto-generated method stub System.out.println(new Test().test());;} int test(){ try { return func1();} finally { return func2();} } int func1(){ System.out.println(”func1“);return 1;} int func2(){ System.out.println(”func2“);return 2;} }-----------執(zhí)行結(jié)果----------------- func1 func2 2 結(jié)論:finally中的代碼比return 和break語句后執(zhí)行 12、final, finally, finalize的區(qū)別。 final 用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。 內(nèi)部類要訪問局部變量,局部變量必須定義成final類型,例如,一段代碼…… finally是異常處理語句結(jié)構(gòu)的一部分,表示總是執(zhí)行。 finalize是Object類的一個方法,在垃圾收集器執(zhí)行的時候會調(diào)用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關(guān)閉文件等。JVM不保證此方法總被調(diào)用 5、運(yùn)行時異常與一般異常有何異同? 異常表示程序運(yùn)行過程中可能出現(xiàn)的非正常狀態(tài),運(yùn)行時異常表示虛擬機(jī)的通常操作中可能遇到的異常,是一種常見運(yùn)行錯誤。java編譯器要求方法必須聲明拋出可能發(fā)生的非運(yùn)行時異常,但是并不要求必須聲明拋出未被捕獲的運(yùn)行時異常。 15、error和exception有什么區(qū)別? error 表示恢復(fù)不是不可能但很困難的情況下的一種嚴(yán)重問題。比如說內(nèi)存溢出。不可能指望程序能處理這樣的情況。exception 表示一種設(shè)計或?qū)崿F(xiàn)問題。也就是說,它表示如果程序運(yùn)行正常,從不會發(fā)生的情況。 50、Java中的異常處理機(jī)制的簡單原理和應(yīng)用。 異常是指java程序運(yùn)行時(非編譯)所發(fā)生的非正常情況或錯誤,與現(xiàn)實生活中的事件很相似,現(xiàn)實生活中的事件可以包含事件發(fā)生的時間、地點(diǎn)、人物、情節(jié)等信息,可以用一個對象來表示,Java使用面向?qū)ο蟮姆绞絹硖幚懋惓?,它把程序中發(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)該死掉的錯誤; 33、請寫出你最常見到的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。unknowntypeException illegalArgumentException 96、JAVA語言如何進(jìn)行異常處理,關(guān)鍵字:throws,throw,try,catch,finally分別代表什么意義?在try塊中可以拋出異常嗎? 99、java中有幾種方法可以實現(xiàn)一個線程?用什么關(guān)鍵字修飾同步方法? stop()和suspend()方法為何不推薦使用? java5以前,有如下兩種: 表示一個Thread的匿名子類的實例對象,子類加上run方法后的代碼如下: new Thread(){ public void run(){ } }.start(); notify()重新啟動線程。 13、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的講解一定要配合例子代碼來說明,才顯得自己真明白。package com.huawei.interview; public class MultiThread { /** * @param args */ public static void main(String[] args){ // TODO Auto-generated method stub new Thread(new Thread1()).start();try { Thread.sleep(10);} catch(InterruptedException e){ // TODO Auto-generated catch block e.printStackTrace();} new Thread(new Thread2()).start();} private static class Thread1 implements Runnable { @Override public void run(){ // TODO Auto-generated method stub //由于這里的Thread1和下面的Thread2內(nèi)部run方法要用同一對象作為監(jiān)視器,我們這里不能用this,因為在Thread2里面的this和這個Thread1的this不是同一個對象。我們用MultiThread.class這個字節(jié)碼對象,當(dāng)前虛擬機(jī)里引用這個變量時,指向的都是同一個對象。synchronized(MultiThread.class){ System.out.println(”enter thread1...“); System.out.println(”thread1 is waiting“);try { //釋放鎖有兩種方式,System.out.println(”enter thread2...“); System.out.println(”thread2 notify other thread can release wait status..“);//由于notify方法并不釋放鎖,即使thread2調(diào)用下面的sleep方法休息了10毫秒,但thread1仍然不會執(zhí)行,因為thread2沒有釋放鎖,所以Thread1無法得不到鎖。 MultiThread.class.notify(); System.out.println(”thread2 is sleeping millisecond...“);try { Thread.sleep(10);} catch(InterruptedException e){ // TODO Auto-generated catch block e.printStackTrace();} System.out.println(”thread2 is going on...“);System.out.println(”thread2 is being over!“);} } } } 16、同步和異步有何異同,在什么情況下分別使用他們?舉例說明。 如果數(shù)據(jù)將在線程間共享。例如正在寫的數(shù)據(jù)以后可能被另一個線程讀到,或者正在讀的數(shù)據(jù)可能已經(jīng)被另一個線程寫過了,那么這些數(shù)據(jù)就是共享數(shù)據(jù),必須進(jìn)行同步存取。 當(dāng)應(yīng)用程序在對象上調(diào)用了一個需要花費(fèi)很長時間來執(zhí)行的方法,并且不希望讓程序等待方法的返回時,就應(yīng)該使用異步編程,在很多情況下采用異步途徑往往更有效率。 ten 17.下面兩個方法同步嗎?(自己發(fā)明) class Test { synchronized static void sayHello3(){ } synchronized void getX(){} } 56、多線程有幾種實現(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)的線程,注意并不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。 30、啟動一個線程是用run()還是start()?.啟動一個線程是調(diào)用start()方法,使線程就緒狀態(tài),以后可以被調(diào)度為運(yùn)行狀態(tài),一個線程必須關(guān)聯(lián)一些具體的執(zhí)行代碼,run()方法是該線程所關(guān)聯(lián)的執(zhí)行代碼。 47、當(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。 58、線程的基本概念、線程的基本狀態(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)。 71、簡述synchronized和java.util.concurrent.locks.Lock的異同 ? 主要相同點(diǎn):Lock能完成synchronized所實現(xiàn)的所有功能 主要不同點(diǎn):Lock有比synchronized更精確的線程語義和更好的性能。synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,并且必須在finally從句中釋放。Lock還有更強(qiáng)大的功能,例如,它的tryLock方法可以非阻塞方式去拿鎖。 舉例說明(對下面的題用lock進(jìn)行了改寫): package com.huawei.interview; import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock; public class ThreadTest { /** * @param args */ private int j; private Lock lock = new ReentrantLock();public static void main(String[] args){ // TODO Auto-generated method stub ThreadTest tt = new ThreadTest();for(int i=0;i<2;i++){ new Thread(tt.new Adder()).start();new Thread(tt.new Subtractor()).start();} } private class Subtractor implements Runnable { @Override public void run(){ // TODO Auto-generated method stub while(true){ /*synchronized(ThreadTest.this){ System.out.println(”j--=“ + j--);//這里拋異常了,鎖能釋放嗎? }*/ lock.lock();try { System.out.println(”j--=“ + j--);}finally { lock.unlock();} } } } private class Adder implements Runnable { @Override public void run(){ // TODO Auto-generated method stub while(true) { /*synchronized(ThreadTest.this){ System.out.println(”j++=“ + j++);}*/ lock.lock();try { System.out.println(”j++=“ + j++);}finally { lock.unlock();} } } } } 28、設(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=new ThreadTest1();Inc inc=tt.new Inc();Dec dec=tt.new Dec();for(int i=0;i<2;i++){ Thread t=new Thread(inc);t.start();t=new Thread(dec);t.start();} } private synchronized void inc(){ j++;System.out.println(Thread.currentThread().getName()+”-inc:“+j);} private synchronized void dec(){ j--;System.out.println(Thread.currentThread().getName()+”-dec:“+j); } class Inc implements Runnable{ public void run(){ for(int i=0;i<100;i++){ inc();} } } class Dec implements Runnable{ public void run(){ for(int i=0;i<100;i++){ dec();} } } } ----------隨手再寫的一個-------------class A { JManger j =new JManager();main(){ new A().call();} void call { for(int i=0;i<2;i++){ new Thread(new Runnable(){ public void run(){while(true){j.accumulate()}}}).start();new Thread(new Runnable(){ public void run(){while(true){j.sub()}}}).start();} } } class JManager { private j = 0; public synchronized void subtract(){ j--} public synchronized void accumulate(){ j++;} } 28、子線程循環(huán)10次,接著主線程循環(huán)100,接著又回到子線程循環(huán)10次,接著再回到主線程又循環(huán)100,如此循環(huán)50次,請寫出程序。 最終的程序代碼如下: public class ThreadTest { /** * @param args */ public static void main(String[] args){ // TODO Auto-generated method stub new ThreadTest().init();} public void init(){ final Business business = new Business();new Thread(new Runnable(){ public void run(){ for(int i=0;i<50;i++){ business.SubThread(i);} } } ).start(); for(int i=0;i<50;i++){ business.MainThread(i);} } private class Business { boolean bShouldSub = true;//這里相當(dāng)于定義了控制該誰執(zhí)行的一個信號燈 public synchronized void MainThread(int i){ if(bShouldSub)try { this.wait();} catch(InterruptedException e){ // TODO Auto-generated catch block e.printStackTrace();} for(int j=0;j<5;j++){ System.out.println(Thread.currentThread().getName()”:i=“ + i +”,j=“ + j);} bShouldSub = true;this.notify();} public synchronized void SubThread(int i){ if(!bShouldSub)try { this.wait();} catch(InterruptedException e){ // TODO Auto-generated catch block e.printStackTrace();} + for(int j=0;j<10;j++){ System.out.println(Thread.currentThread().getName()+ ”:i=“ + i +”,j=“ + j);} bShouldSub = false;this.notify();} } } 備注:不可能一上來就寫出上面的完整代碼,最初寫出來的代碼如下,問題在于兩個線程的代碼要參照同一個變量,即這兩個線程的代碼要共享數(shù)據(jù),所以,把這兩個線程的執(zhí)行代碼搬到同一個類中去: package com.huawei.interview.lym; public class ThreadTest { private static boolean bShouldMain = false; public static void main(String[] args){ // TODO Auto-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 = new String(”“); new Thread(new Runnable(){ public void run() { for(int i=0;i<50;i++){ synchronized(ThreadTest.class){ if(bShouldMain){ try { ThreadTest.class.wait();} catch(InterruptedException e){ e.printStackTrace();} } for(int j=0;j<10;j++){ System.out.println(Thread.currentThread().getName()+ ”i=“ + i + ”,j=“ + j);} bShouldMain = true;ThreadTest.class.notify();} } } }).start(); for(int i=0;i<50;i++){ synchronized(ThreadTest.class){ if(!bShouldMain){ try { ThreadTest.class.wait();} catch(InterruptedException e){ e.printStackTrace();} } for(int j=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 Lock lock = new ReentrantLock();private static Condition subThreadCondition = lock.newCondition();private static boolean bBhouldSubThread = false;public static void main(String [] args){ ExecutorService threadPool = Executors.newFixedThreadPool(3);threadPool.execute(new Runnable(){ public void run(){ for(int i=0;i<50;i++){ lock.lock();try { if(!bBhouldSubThread)subThreadCondition.await();for(int j=0;j<10;j++){ System.out.println(Thread.currentThread().getName()+ ”,j=“ + j);} bBhouldSubThread = false;subThreadCondition.signal();}catch(Exception e){ } finally { lock.unlock();} } } });threadPool.shutdown();for(int i=0;i<50;i++){ lock.lock();try { if(bBhouldSubThread)subThreadCondition.await();for(int j=0;j<10;j++){ System.out.println(Thread.currentThread().getName()+ ”,j=“ + j);} bBhouldSubThread = true;subThreadCondition.signal();}catch(Exception e){ } finally { lock.unlock();} } } } 3、介紹Collection框架的結(jié)構(gòu) 答:隨意發(fā)揮題,天南海北誰便談,只要讓別覺得你知識淵博,理解透徹即可。 3、Collection框架中實現(xiàn)比較要實現(xiàn)什么接口 comparable/comparator 3、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è)置增長空間的方法??偨Y(jié):即Vector增長原來的一倍,ArrayList增加原來的0.5倍。 4、HashMap和Hashtable的區(qū)別 (條理上還需要整理,也是先說相同點(diǎn),再說不同點(diǎn))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 5、List 和 Map 區(qū)別? 一個是存儲單列數(shù)據(jù)的集合,另一個是存儲鍵和值這樣的雙列數(shù)據(jù)的集合,List中存儲的數(shù)據(jù)是有順序,并且允許重復(fù);Map中存儲的數(shù)據(jù)是沒有順序的,其鍵是不能重復(fù)的,它的值是可以有重復(fù)的。 35、List, Set, Map是否繼承自Collection接口? List,Set是,Map不是 109、List、Map、Set三個接口,存取元素時,各有什么特點(diǎn)? 這樣的題屬于隨意發(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取元素時,沒法說取 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)來明確說明取 4、去掉一個Vector集合中重復(fù)的元素 Vector newVector = new Vector();For(int i=0;i 9、Collection 和 Collections的區(qū)別。 Collection是集合類的上級接口,繼承與他的接口主要有Set 和List.Collections是針對集合類的一個幫助類,他提供一系列靜態(tài)方法實現(xiàn)對各種集合的搜索、排序、線程安全化等操作。 39、Set里的元素是不能重復(fù)的,那么用什么方法來區(qū)分重復(fù)與否呢? 是用==還是equals()? 它們有何區(qū)別? Set里的元素是不能重復(fù)的,元素重復(fù)與否是使用equals()方法進(jìn)行判斷的。equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋,為的是當(dāng)兩個分離的對象的內(nèi)容和類型相配的話,返回真值。 53、你所知道的集合類都有哪些?主要方法? 最常用的集合類是 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下按點(diǎn)操作符,很自然的這些方法就出來了。我記住的一些思想就是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。 45、兩個對象值相同(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)的。 46、TreeSet里面放對象,如果同時放入了父類和子類的實例對象,那比較時使用的是父類的compareTo方法,還是使用的子類的compareTo方法,還是拋異常! (應(yīng)該是沒有針對問題的確切的答案,當(dāng)前的add方法放入的是哪個對象,就調(diào)用哪個對象的compareTo方法,至于這個compareTo方法怎么做,就看當(dāng)前這個對象的類中是如何編寫這個方法的)實驗代碼: public class Parent implements Comparable { private int age = 0;public Parent(int age){ this.age = age;} public int compareTo(Object o){ // TODO Auto-generated method stub System.out.println(”method of parent“);Parent o1 =(Parent)o;return age>o1.age?1:age } public class Child extends Parent { public Child(){ super(3);} public int compareTo(Object o){ // TODO Auto-generated method stub System.out.println(”method of child“);// Child o1 =(Child)o;return 1;} } public class TreeSetTest { /** * @param args */ public static void main(String[] args){ // TODO Auto-generated method stub TreeSet set = new TreeSet();set.add(new Parent(3));set.add(new Child());set.add(new Parent(4));System.out.println(set.size());} } 112、說出一些常用的類,包,接口,請各舉5個 要讓人家感覺你對java ee開發(fā)很熟,所以,不能僅僅只列core java中的那些東西,要多列你在做ssh項目中涉及的那些東西。就寫你最近寫的那些程序中涉及的那些類。 常用的類:BufferedReader BufferedWriter FileReader FileWirter String Integer java.util.Date,System,Class,List,HashMap 常用的包:java.lang java.io java.util java.sql ,javax.servlet,org.apache.strtuts.action,org.hibernate 常用的接口:Remote List Map Document NodeList ,Servlet,HttpServletRequest,HttpServletResponse,Transaction(Hibernate)、Session(Hibernate),HttpSession 100、java中有幾種類型的流?JDK為每種類型的流提供了一些抽象類以供繼承,請說出他們分別是哪些類? 字節(jié)流,字符流。字節(jié)流繼承于InputStream OutputStream,字符流繼承于InputStreamReader OutputStreamWriter。在java.io包中還有許多其他的流,主要是為了提高性能和使用方便。102、字節(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è)別寫入或讀取字符串提供了一點(diǎn)點(diǎn)方便。 字符向字節(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 = ”中國人“;/*FileOutputStream fos = new FileOutputStream(”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 = new char[1024];int len = fr.read(buf);String myStr = new String(buf,0,len);System.out.println(myStr);*/ /*FileInputStream fr = new FileInputStream(”1.txt“);byte[] buf = new byte[1024];int len = fr.read(buf);String myStr = new String(buf,0,len,”UTF-8“);System.out.println(myStr);*/ BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(”1.txt“),”UTF-8"));String myStr = br.readLine();br.close();System.out.println(myStr);} } 105、什么是java序列化,如何實現(xiàn)java序列化?或者請解釋Serializable接口的作用。