Java
Java 中如何實(shí)現(xiàn)序列化,有什么意義?
序列化是處理對象流的機(jī)制。
可以對流化后的對象進(jìn)行讀寫操作。
可傳輸于網(wǎng)絡(luò)之間。
序列化可解決對象流讀寫操作時可能引發(fā)數(shù)據(jù)亂序的問題。
序列化除了能夠?qū)崿F(xiàn)對象的持久化之外,還能夠用于對象的深度克隆
實(shí)現(xiàn)序列化操作:
1.?實(shí)現(xiàn) Serializable 接口
2.?構(gòu)造對象輸出流并通過 writeObject(Object)方法就可以將實(shí)現(xiàn)對象輸出
3.?反序列化創(chuàng)建對象輸入流,然后通過 readObject 方法從流中讀取對象。
?
簡述 synchronized 和 Lock的異同?
相同:
Lock 能完成 synchronized 所實(shí)現(xiàn)的所有功能;
不同:
Lock 有比synchronized 更精確的線程語義和更好的性能,而且不強(qiáng)制性的要求獲得鎖。
synchronized 會自動釋放鎖,而 Lock 需要手動釋放
?
線程的基本狀態(tài)以及狀態(tài)之間的關(guān)系?
其中 Running 表示運(yùn)行狀態(tài),Runnable 表示就緒狀態(tài)(萬事俱備,只欠CPU),Blocked 表示阻塞狀態(tài),阻塞狀態(tài)又有多種情況,可能是因?yàn)檎{(diào)用 wait()
方法進(jìn)入等待池,也可能是執(zhí)行同步方法或同步代碼塊進(jìn)入等鎖池,或者是調(diào)用了 sleep()方法或 join()方法等待休眠或其他線程結(jié)束,或是因?yàn)榘l(fā)生了 I/O 中斷。
?
?
?
什么是線程池(thread pool)?
減少線程創(chuàng)建和銷毀對象的開銷。
Executor 接口定義一個執(zhí)行線程的工具。它的子類型線程池接口是 ExecutorService。
工具類 Executors 提供了靜態(tài)工廠方法,生成的線程池,如下所示:
newSingleThreadExecutor:創(chuàng)建一個單線程的線程池。單線程串行執(zhí)行所有任務(wù)。如果線程異常結(jié)束,那么會有一個新的線程來替代。此線程池保證所有任務(wù)按提交順序執(zhí)行。
newFixedThreadPool:創(chuàng)建固定大小的線程池。每次提交一個任務(wù)就創(chuàng)建一個線程,直到線程達(dá)到線程池的最大大小。線程池的大小一旦達(dá)到最大值就會保持不變,如果某個線程因?yàn)閳?zhí)行異常而結(jié)束,那么線程池會補(bǔ)充一個新線程。
newCachedThreadPool:創(chuàng)建一個可緩存的線程池。如果線程池的大小超過了處理任務(wù)所需要的線程,那么就會回收部分空閑(60 秒不執(zhí)行任務(wù))的線程,當(dāng)任務(wù)數(shù)增加時,此線程池又可以智能的添加新線程來處理任務(wù)。此線程池不會對線程池大小做限制,線程池大小完全依賴于操作系統(tǒng)(或者說 JVM)能夠創(chuàng)建的最大線程大小。
newScheduledThreadPool:創(chuàng)建一個大小無限的線程池。此線程池支持定時以及周期性執(zhí)行任務(wù)的需求。
newSingleThreadExecutor:創(chuàng)建一個單線程的線程池。此線程池支持定時以及周期性執(zhí)行任務(wù)的需求。
如果希望在服務(wù)器上使用線程池,強(qiáng)烈建議使用 newFixedThreadPool方法來創(chuàng)建線程池,這樣能獲得更好的性能。
?
啟動一個線程是調(diào)用 run()還是 start()方法
啟動一個線程是調(diào)用 start()方法,使線程所代表的虛擬處理機(jī)處于可運(yùn)行狀態(tài),這意味著它可以由 JVM 調(diào)度并執(zhí)行,這并不意味著線程就會立即運(yùn)行。run()方法是線程啟動后要進(jìn)行回調(diào)(callback)的方法。
?
synchronized 關(guān)鍵字的用法?
synchronized 關(guān)鍵字可以將對象或者方法標(biāo)記為同步,以實(shí)現(xiàn)對對象和方法的互斥訪問,可以用 synchronized(對象) { … }定義同步代碼塊,或者在聲明方法時將 synchronized 作為方法的修飾符。
?
編寫多線程程序有幾種實(shí)現(xiàn)方式
Java 5 以前實(shí)現(xiàn)多線程有兩種實(shí)現(xiàn)方法:一種是繼承 Thread 類;另一種是實(shí)現(xiàn)Runnable 接口。兩種方式都要通過重寫 run()方法來定義線程的行為,推薦使用后者,因?yàn)?Java 中的繼承是單繼承,一個類有一個父類,如果繼承了 Thread 類就無法再繼承其他類了,顯然使用 Runnable 接口更為靈活。
Java 5 以后創(chuàng)建線程還有第三種方式:實(shí)現(xiàn) Callable 接口,該接口中的 call方法可以在線程執(zhí)行結(jié)束時產(chǎn)生一個返回值
?
請說出與線程同步以及線程調(diào)度相關(guān)的方法
wait():使一個線程處于等待(阻塞)狀態(tài),釋放對象的鎖;
sleep():使一個正在運(yùn)行的線程處于睡眠狀態(tài),是一個靜態(tài)方法,調(diào)用此方法要處理 InterruptedException 異常;
notify():喚醒一個處于等待狀態(tài)的線程,當(dāng)然在調(diào)用此方法的時候,并不能確切的喚醒某一個等待狀態(tài)的線程,而是由 JVM 確定喚醒哪個線程,而且與優(yōu)先級無關(guān);
notityAll():喚醒所有處于等待狀態(tài)的線程,該方法并不是將對象的鎖給所有線程,而是讓它們競爭,只有獲得鎖的線程才能進(jìn)入就緒狀態(tài);
線程的 sleep()方法和 yield()方法有什么區(qū)別?
① sleep()方法給其他線程運(yùn)行機(jī)會時不考慮線程的優(yōu)先級;yield()方法只會給相同或更高優(yōu)先級的線程以運(yùn)行的機(jī)會;
② 線程執(zhí)行 sleep()方法后轉(zhuǎn)入阻塞(blocked)狀態(tài),而執(zhí)行 yield()方法后轉(zhuǎn)入就緒(ready)狀態(tài);
③ sleep()方法聲明拋出 InterruptedException(中斷異常),而 yield()方法沒有聲明任何異常;
?
Thread 類的 sleep()方法和對象的 wait()方法都可以讓線程暫停執(zhí)行,它們有什么區(qū)別?
sleep()方法是Thread的靜態(tài)方法
會讓當(dāng)前線程根據(jù)指定的時間暫停,將執(zhí)行機(jī)會讓給其他線程
對象的鎖依然保持,時間到會自動恢復(fù)。
wait()是 Object 類的方法
wait()方法導(dǎo)致當(dāng)前線程放棄對象的鎖,進(jìn)入對象的等待池
只有調(diào)用對象的 notify()或 notifyAll()才能喚醒等待池中的線程進(jìn)入等鎖池,如果線程重獲對象鎖就可以進(jìn)入就緒狀態(tài)。
?
接口和抽象類的區(qū)別
抽象類和接口都不能夠?qū)嵗?/p>
一個類如果繼承了某個抽象類或者實(shí)現(xiàn)了某個接口都需要對其中的抽象方法全部進(jìn)行實(shí)現(xiàn),否則該類仍然需要被聲明為抽象類。
抽象類可以定義構(gòu)造器;而接口中不能定義構(gòu)造器。
抽象類可以有抽象方法和具體方法;接口方法全部都是抽象方法。
抽象類中的成員可以是 private、默認(rèn)、protected、public 的,而接口中的成員全都是 public 的。
抽象類中可以定義成員變量,而接口中定義的成員變量實(shí)際上都是常量。
有抽象方法的類必須被聲明為抽象類,而抽象類未必要有抽象方法。
?
?
TreeMap 和 TreeSet 在排序時如何比較元素?Collections 工具類中的 sort()方法如何比較元素?
TreeSet 要求存放的對象所屬的類必須實(shí)現(xiàn) Comparable 接口,該接口提供了比較元素的 compareTo()方法,當(dāng)插入元素時會回調(diào)該方法比較元素的大小。
TreeMap 要求存放的鍵值對的鍵必須實(shí)現(xiàn) Comparable 接口從而根據(jù)鍵對元素進(jìn)行排序。
Collections 工具類的 sort 方法有兩種形式:
第一種要求待排序容器中存放的對象實(shí)現(xiàn) Comparable 接口以實(shí)現(xiàn)元素的比較;
第二種不強(qiáng)制性要求容器中元素的比較,但是要求傳入第二個參數(shù)是Comparator 接口的子類型(需要重寫 compare 方法實(shí)現(xiàn)元素的比較),相當(dāng)于臨時定義的排序規(guī)則。
?
ArrayList、Vector、LinkedList 的存儲性能和特性
ArrayList 和 Vector 都是數(shù)組方式存儲數(shù)據(jù)
數(shù)組元素數(shù)大于實(shí)際存儲的數(shù)據(jù)以便增加元素
按序號索引元素,插入元素涉及數(shù)組元素移動
Vector 中的方法由于添加了 synchronized 修飾。
LinkedList 使用雙向鏈表實(shí)現(xiàn)存儲
按序號索引數(shù)據(jù)需要進(jìn)行前向或后向遍歷,但是插入數(shù)據(jù)時只需要記錄本項(xiàng)的前后項(xiàng)
ArrayList 和LinkedList 可以通過Collections 中的 synchronizedList 方法將其轉(zhuǎn)換成線程安全的容器后再使用。
?
?
當(dāng)一個線程進(jìn)入一個對象的 synchronized 方法 A 之后,其它線程是否可進(jìn)入此對象的 synchronized 方法 B?
不能。其它線程只能訪問該對象的非同步方法。
非靜態(tài)方法上的 synchronized 修飾符要求執(zhí)行方法時要獲得對象的鎖。
如果已經(jīng)進(jìn)入A 方法說明對象鎖已經(jīng)被取走,那么試圖進(jìn)入 B 方法的線程就只能在等鎖池(注意不是等待池哦)中等待對象的鎖。
?
?
?
List、Map、Set 三個接口存取元素時,各有什么特點(diǎn)?
List 以特定索引來存取元素,可以有重復(fù)元素。
Set 不能存放重復(fù)元素(用對象的equals()方法來區(qū)分元素是否重復(fù))。
Map 保存鍵值對,映射關(guān)系可以是一對一或多對一。
如何實(shí)現(xiàn)對象克???
1). 實(shí)現(xiàn) Cloneable 接口并重寫 Object 類中的 clone()方法;
2). 實(shí)現(xiàn) Serializable 接口,通過對象的序列化和反序列化實(shí)現(xiàn)克隆,可以實(shí)現(xiàn)深度克隆,
?
?
解釋內(nèi)存中的棧、堆和方法區(qū)的用法。
棧中存放的是局部變量、方法參數(shù)、方法幀。線程有私有的棧不對外共享。執(zhí)行方法時,作為方法幀入棧,當(dāng)執(zhí)行完后出棧。
堆中主要用來存放的是對象。為所有的線程所共享。
方法區(qū)中存放的都是一些靜態(tài)的數(shù)據(jù),比如static變量、class等。為共享區(qū)域。方法區(qū)中都是存放的永遠(yuǎn)唯一的元素。
?
?
列出一些你常見的運(yùn)行時異常?
ArithmeticException(算術(shù)異常)
ClassCastException (類轉(zhuǎn)換異常)
IllegalArgumentException (非法參數(shù)異常)
IndexOutOfBoundsException (下標(biāo)越界異常)
NullPointerException (空指針異常)
SecurityException (安全異常)
?
final、finally、finalize 的區(qū)別。
final
(1)?修飾類:表示該類不能被繼承;
(2)?修飾方法:表示方法不能被重寫;
(3)?修飾變量:表示變量只能一次賦值以后值不能被修改(常量)。
finally
通常放在 try…catch…的后面
這就意味著程序無論正常執(zhí)行還是發(fā)生異常,這里的代碼只要 JVM 不關(guān)閉都能執(zhí)行,
可以將釋放外部資源的代碼寫在 finally 塊中。
finalize
Object 類中定義的方法
垃圾收集器在銷毀對象時調(diào)用的,通過重寫 finalize()方法可以整理系統(tǒng)資源或者執(zhí)行其他清理工作。
?
?
?
Java 中會存在內(nèi)存泄漏嗎,請簡單描述
理論上 Java 因?yàn)橛欣厥諜C(jī)制不會存在內(nèi)存泄露問題;
而在實(shí)際開發(fā)中,可能會存在無用但可達(dá)的對象,這些對象不能被 GC 回收,因此也會導(dǎo)致內(nèi)存泄露的發(fā)生。
例如Hibernate 的 Session(一級緩存)中的對象屬于持久態(tài),垃圾回收器是不會回收這些對象的,然而這些對象中可能存在無用的垃圾對象,如果不及時關(guān)閉(close)或清空(flush)一級緩存就可能導(dǎo)致內(nèi)存泄露。
?
?
GC 是什么?為什么要有 GC?
對內(nèi)存堆中已經(jīng)死亡的或者長時間沒有使用的對象進(jìn)行回收
防止內(nèi)存泄露,有效的利用可使用的內(nèi)存。
不能實(shí)時的調(diào)用垃圾回收器對某個對象進(jìn)行垃圾回收。
垃圾回收機(jī)制有很多種:
分代復(fù)制垃圾回收
標(biāo)記垃圾回收
增量垃圾回收等。
GC采用“分代式垃圾收集”。
將堆內(nèi)存劃分為不同的區(qū)域:
伊甸園(Eden):對象誕生的區(qū)域。
幸存者樂園(Survivor):在Eden幸存下來的對象。
終身頤養(yǎng)園(Tenured):保存老的幸存對象。年輕代收集(Minor-GC)過程是不會觸及這個地方的。當(dāng)年輕代收集不能把對象放進(jìn)Tenured時,就會觸發(fā)一次完全收集(Major-GC)
與垃圾回收相關(guān)的 JVM 參數(shù):
-Xms / -Xmx — 堆的初始大小 / 堆的最大大小
-Xmn — 堆中年輕代的大小
-XX:-DisableExplicitGC — 讓 System.gc()不產(chǎn)生任何作用
-XX:+PrintGCDetails — 打印 GC 的細(xì)節(jié)
-XX:+PrintGCDateStamps — 打印 GC 操作的時間戳
-XX:NewSize / XX:MaxNewSize — 設(shè)置新生代大小/新生代最大大小
-XX:NewRatio — 可以設(shè)置老生代和新生代的比例
-XX:PrintTenuringDistribution — 設(shè)置每次新生代 GC 后輸出幸存者樂園中對象年齡的分布
-XX:InitialTenuringThreshold / -XX:MaxTenuringThreshold:設(shè)置老年代閥值的初始值和最大值
-XX:TargetSurvivorRatio:設(shè)置幸存區(qū)的目標(biāo)使用率
?
靜態(tài)變量和實(shí)例變量的區(qū)別
靜態(tài)變量:?
static 修飾
屬于類,也稱為類變量
靜態(tài)變量在內(nèi)存中有且僅有一個拷貝;
靜態(tài)變量可以實(shí)現(xiàn)讓多個對象共享內(nèi)存。
實(shí)例變量:
必須依存于某一實(shí)例,通過對象才能訪問。
?
事物的四個特點(diǎn)——ACID是靠什么保證的
原子性
由undolog日志進(jìn)行保證,記錄需要回滾的信息,事物回滾時撤銷已經(jīng)執(zhí)行成功的sql
一致性
由其他三大特征保證
隔離性
是由MVCC多版本并發(fā)控制保證
持久性
由redolog保證,mysql修改數(shù)據(jù)時,會在redolog中記錄一份日志數(shù)據(jù),就算數(shù)據(jù)沒有保存成功,只要日志保存成功,數(shù)據(jù)就不會消失
?
?
try{}里有一個 return 語句,那么緊跟在這個 try 后的finally{}里的代碼會不會被執(zhí)行,什么時候被執(zhí)行,在 return前還是后?
會執(zhí)行,在方法返回調(diào)用者前執(zhí)行。
如果存在 finally 代碼塊,try中的 return 語句不會立馬返回調(diào)用者,而是記錄下返回值待 finally 代碼塊執(zhí)行完畢之后再向調(diào)用者返回其值,然后如果在 finally 中修改了返回值,就會返回修改后的值。
?
Collection 和 Collections 的區(qū)別?
Collection 是一個接口,它是 Set、List 等容器的父接口;
Collections 是個一個工具類,這些方法包括對容器的搜索、排序、線程安全化等等。
?
JVM、JRE和JDK的關(guān)系
JVM
Java Virtual Machine是Java虛擬機(jī),Java程序需要運(yùn)行在虛擬機(jī)上,不同的平臺有自己的虛擬機(jī),因此Java語言可以實(shí)現(xiàn)跨平臺。
JRE
Java Runtime Environment包括Java虛擬機(jī)和Java程序所需的核心類庫等。核心類庫主要是java.lang包:如基本數(shù)據(jù)類型、基本數(shù)學(xué)函數(shù)、字符串處理、線程、異常處理類等
JDK
其中包含了Java的開發(fā)工具,也包括了JRE。所以安裝了JDK,就無需再單獨(dú)安裝JRE了。
面向?qū)ο笕筇匦裕?/strong>
其中Java 面向?qū)ο缶幊倘筇匦裕悍庋b 繼承 多態(tài)
封裝
封裝把一個對象的屬性私有化
提供一些可以被外界訪問的屬性的方法
繼承
在父類的基礎(chǔ)上建立子類
子類可以增加屬性方法,也可以用父類的屬性方法,但不能選擇性地繼承。
關(guān)于繼承如下 3 點(diǎn)請記?。?/p>
1.?子類擁有父類非 private 的屬性和方法。
2.?子類可以擁有自己屬性和方法。
3.?子類可以重寫父類的方法。
多態(tài)
父類的引用指向子類的具體實(shí)現(xiàn),調(diào)用的實(shí)現(xiàn)方法,必須在由程序運(yùn)行期間才能決定。
實(shí)現(xiàn)多態(tài)的兩種形式:
繼承(多個子類對同一方法的重寫)和接口(實(shí)現(xiàn)接口并覆蓋接口中同一方法)。
多態(tài)實(shí)現(xiàn)三個必要條件
繼承、重寫、向上轉(zhuǎn)型。
繼承:在多態(tài)中必須存在有繼承關(guān)系的子類和父類。
重寫:子類對父類中某些方法進(jìn)行重新定義。
向上轉(zhuǎn)型:將子類的引用賦給父類對象。
?
Overload和Override的區(qū)別。
如果在子類中定義某方法與其父類有相同的名稱和參數(shù),我們說該方法被重寫 (Overriding)。
如果在一個類中定義了多個同名的方法,它們或有不同的參數(shù)個數(shù)或有不同的參數(shù)類型,則稱為方法的重載(Overloading)。Overloaded的方法是可以改變返回值的類型
?
?
“==”與“equals()”的區(qū)別。
"=="判斷的是兩個對象的內(nèi)存地址是否一樣
equals 是 Object 類的方法,Object 對它的實(shí)現(xiàn)是比較內(nèi)存地址,我們可以重寫這個方法來自定義 “相等”這個概念。
?
線程池的原理,為什么要創(chuàng)建線程池?
在線程池中維護(hù)一組線程,這些線程可以重復(fù)利用,以減少線程的創(chuàng)建和銷毀的開銷。
線程池中的線程被維護(hù)在一個隊(duì)列中,新來的任務(wù)會被插入到隊(duì)列的尾部。當(dāng)線程池中有空閑線程時,它會從隊(duì)列的頭部取出任務(wù)。
最大線程數(shù)限制了線程池中最多能有多少個線程同時工作
輔助線程要監(jiān)控線程池的狀態(tài),及時調(diào)整線程池的大小。
?
?
Java 有沒有 goto?
goto 是 Java 中的保留字,在目前版本的 Java 中沒有使用。
?
&和&&的區(qū)別?
&運(yùn)算符有兩種用法:(1)按位與;(2)邏輯與。
&&運(yùn)算符是短路與運(yùn)算。
邏輯與跟短路與的差別是非常巨大的,雖然二者都要求運(yùn)算符左右兩端的布爾值都是true 整個表達(dá)式的值才是 true。
&&之所以稱為短路運(yùn)算是因?yàn)椋绻?amp;&左邊的表達(dá)式的值是 false,右邊的表達(dá)式會被直接短路掉,不會進(jìn)行運(yùn)算。
例如在驗(yàn)證用戶登錄時判定用戶名不是 null 而且不是空字符串,應(yīng)當(dāng)寫為:username != null &&!username.equals(“”),二者的順序不能交換,更不能用&運(yùn)算符,因?yàn)榈谝粋€條件如果不成立,根本不能進(jìn)行字符串的 equals 比較,否則會產(chǎn)生空值異常。
?
switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上?
在 Java 5 以前,switch(expr)中,expr 只能是 byte、short、char、int。從 Java5 開始,Java 中引入了枚舉類型,expr 也可以是 enum 類型,從 Java 7 開始,expr 還可以是字符串(String),但是長整型(long)在目前所有的版本中都是不可以的
數(shù)組有沒有 length()方法?String 有沒有 length()方法?
數(shù)組沒有 length()方法,有 length 的屬性。String 有 length()方法。JavaScript中,獲得字符串的長度是通過 length 屬性得到的,這一點(diǎn)容易和 Java 混淆。
構(gòu)造器(constructor)是否可被重寫(override)
構(gòu)造器不能被繼承,因此不能被重寫,但可以被重載。
兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對
兩個值相同,哈希碼一定相同,哈希碼相同,兩個值不一定相同
是否可以繼承 String 類?
String 類是 final 類,不可以被繼承。
String 和 StringBuilder、StringBuffer 的區(qū)別
其中 String 是只讀字符串,內(nèi)容不能被改變。
而 StringBuffer/StringBuilder 類表示的字符串對象可以直接進(jìn)行修改。
StringBuilder沒有被synchronized 修飾
?
?
接口是否可繼承接口?抽象類是否可實(shí)現(xiàn)接口?抽象類是否可繼承具體類?
接口可繼承接口,支持多重繼承。
抽象類可以實(shí)現(xiàn)接口,抽象類可繼承具體類也可以繼承抽象類。
是否可以繼承其它類?是否可以實(shí)現(xiàn)接口?
可以繼承其他類或?qū)崿F(xiàn)其他接口
內(nèi)部類可以引用它的包含類(外部類)的成員嗎?有沒有什么限制??
一個內(nèi)部類對象可以訪問創(chuàng)建它的外部類對象的成員,包括私有成員。
?
?
?