《JAVA面試突破專題》

 

 

《JAVA面試突破專題》

面向對象

1、面向對象和麪向過程的區別

面向過程關注於一個功能實現的步驟,按步驟編程實現功能。

面向對象關注於一個功能實現的行爲,將一些行爲封裝爲一個對象來統一調用。

 

面向過程是一種事件爲中心的編程思想。就是分析出解決問題所需的步驟,然後用函數把這些步驟實現,並按順序調用。面向對象是以對象爲中心的編程思想。

 

2、四個基本特性

抽象:Java中抽象的概念最直接的應用就是抽象類和接口,從複雜的業務邏輯中,提煉出它的本質。

封裝:封裝將數據以及加在這些數據上的操作組織在一起,提供給可信的其他類或對象操作。

繼承:繼承就是從一般到特殊的過程。通過繼承可以擁有現有類的所有功能,並在無需重修編寫原來類的情況下對這些功能進行擴展。

多態:多態性是指允許不同類的對象對同一消息作出響應。即同一消息可以根據發送對象的不同而採用多種不同的行爲方式。(發送消息就是函數調用)。實現多態的兩種方式:重寫、重載。

 

封裝考慮內部實現,抽象考慮的是外部行爲。封裝可以隱藏實現細節,使得代碼模塊化;繼承可以擴展已存在的代碼模塊;他們都是爲了解決代碼重用。而多態是爲了實現接口重用,爲了類在繼承和派生的時候,保證使用“家譜”中任一類的實例的某一屬性時的正確使用。

 

3、抽象類和接口的區別

相同點:

都是上層的抽象;

都不能被實例化;

都能包含抽象方法。

不同點:

在抽象類中可以寫非抽象的方法,從而避免在子類中重複書寫他們,提高代碼的複用性;接口中只能有抽象方法(JDK1.8新特性:默認方法(子類不一定要實現)、JDK1.9新特性:私有方法(增強默認方法));

一個類只能繼承一個直接父類(普通類或抽象類),但是可以實現多個接口。

 

4、訪問控制符

private:同類可見

default:同包可見

protected:同包可見,子類可見

public:全局可見

 

 

5、重載和重寫

重載是指一個類中允許存在多個同名函數,而這些函數的參數不同;重寫是指子類重新定義父類的方法。

 

6、構造器Constructor是否可被override?

構造器不允許被重寫。

構造器不是方法,所有用於修飾方法特性的修飾符,都不能用來修飾構造器。

構造器是實例化對象過程中用來初始化這個對象用的。

 

 

 

語言特性

 

1、自動裝箱與拆箱

以問題引入:

689BE89F552B4EF3B85F3DBD28EB1562uploading.4e448015.gif轉存失敗重新上傳取消

 

 

JDK實際編譯的代碼:

7F064622031B4059B0AE52099DC6A5F4uploading.4e448015.gif轉存失敗重新上傳取消

 

將Integer a = 120; 編譯爲:Integer a = Integer.valueOf(120); 就是JDK的自動裝箱操作。

將int e = a; 編譯爲:int e = a.intValue(); 就是JDK的自動拆箱操作。

 

自動裝箱也就是將基本數據類型封裝到對象中的操作,自動拆箱也就是將對象中的基本數據從對象中自動取出。

 

2、String和StringBuffer、StringBuilder的區別

性能差別:StringBuilder > StringBuffer > String;

String對字符串的操作(修改、拼接)其實是在創建新的對象,效率低下;

StringBuffer線程安全、StringBuilder線程不安全

 

3、hashCode和equals方法的關係

hashcode()方法是JDK根據對象的地址或者字符串的值計算出來的int類型的數值(哈希碼值)。

同一對象多次調用hashcode()方法,必須返回相同的數值。

如果兩個對象根據equals()方法比較是相等的,那麼兩個對象調用hashcode()方法返回的結果必須相等。

如果兩個對象根據equals()方法比較是不相等的,那麼兩個對象調用hashcode()方法返回的結果不一定不相等。

 

4、Java中的集合類

Collection下所有子類集合都用於存儲Value,Map下所有子類集合都用於存儲Key-Value。

 

ArrayList是線程不安全的,Vector是線程安全的(二者底層都是數組類型結構),LinkedList線程不安全(底層鏈表類型結構);

ArrayList每次擴容50%,而Vector每次擴容翻倍;

 

Set集合存儲無序的不可重複元素,允許一個null元素。HashSet對象必須定義hashcode()方法,LinkedHashSet具備HashSet的性能,但內部使用鏈表維護元素的順序(插入順序)。TreeSet底層使用樹結構維護有序的元素。

 

HashMap是線程不安全的,可以存儲null值null鍵和;HashTable是線程安全的,不允許存儲null值null鍵;HashTable因爲是線程安全的,所以性能低於HashMap。

 

5、什麼是泛型?爲什麼要使用?泛型擦除?

泛型的本質是參數化類型,也就是說所操作的數據類型被指定爲一個參數。

 

泛型(JDK1.5特性)之前,當方法的參數類型設置爲基類,那麼可以往方法中傳入該基類下任意類型的對象,這樣方法就更具有通用性。另外,將方法參數設置爲接口,更加方便(可實現多個接口)。

這樣存在的問題是,當需要獲取一個值的時候,必須強制類型轉換。而強制裝換類型的時候,容易使用錯誤的類型轉換導致報錯。

 

泛型擦除是指:在Java中使用泛型創建對象時,在編譯期間,所有的泛型信息都會被擦除,編譯後會變成原始類型。

 

6、Java中的異常

IndexOutOfBoundsEecption:元素越界異常;

ArrayIndexOutOfBoundsEecption:多個元素越界異常;

ClassCastException:類型轉換異常;

NullPointerException:空指針異常,null對象的應用;

RuntimeException:運行時異常;

IOException:IO操作異常;

ConnectException:連接失敗異常;

 

7、Java中的BIO,NIO,AIO

BIO(同步阻塞IO):一個連接對應一個線程

當有客戶端連接請求時,服務端需要啓動一個線程進行處理,如果這個連接不做任何處理,會造成不必要的線程開銷,可以通過線程池機制改善,從而實現僞異步IO;

 

NIO(同步非阻塞IO):N個連接對應一個線程

客戶端所有的連接請求都會註冊到多路複用器上,服務端通過一個多路複用器來處理所有請求。

 

AIO(異步非阻塞IO):NIO的2.0版本,引入了異步通道的概念,可以實現異步調用。

異步實現方式:通過java.util.concurrent.Future類來表示異步操作的結果;

在執行異步操作的時候傳入java.nio.channels。

 

8、序列化與反序列化

序列化是指將對象的狀態信息轉換爲可以存儲或傳輸的形式的過程,通過序列化可以將對象的狀態保存爲字節數組,需要的時候再將字節數組反序列化爲對象。

 

9、IO和NIO區別

NIO是Java1.4的新特性,提供了與標準IO不同的工作方式:

標準IO基於字節流和字符流進行操作,而NIO是基於通道(Channel)和緩衝區(Buffer)進行操作,數據從通道讀取到緩衝區中,或者從緩衝區寫入到通道。

NIO引入了選擇器(Selectors)概念,選擇器用於監聽多個通道的事件(比如:連接打開、可讀、可寫),因此NIO可以通過一個線程監聽多個數據通道。相比標準IO爲每一個連接創建一個線程,NIO大大降低了線程創建的資源開銷。

 

 

多線程

1、多線程的實現方式

通常使用繼承Thread類或實現Runnable接口

還可以通過Callable接口實現。

 

2、線程的狀態轉換

new 新建線程

Runnable 可運行狀態(執行start()方法,CPU決定是否運行)

Blocking 阻塞狀態(線程被阻塞於鎖)

Waiting 等待、計時等待(等待某些條件成熟)

Stop 終止狀態(線程運行結束)

 

3、sleep和wait的區別

1、sleep()是線程Thread的方法,而wait()是Object對象的方法。

2、sleep()不會釋放對象鎖、wait()會釋放對象鎖

3、sleep()可以在任何地方調用,wait()方法之可以在同步方法或同步塊中使用。

 

yield() 當前線程出讓cpu佔有權,當前線程變成可運行狀態。

wait()\notify()\notifyAll()

調用以前,當前線程必須要持有鎖,調用它們線程會釋放鎖,等待通知機制。

notify() 喚醒一個線程(謹慎使用),具體喚醒哪個線程,由CPU決定。

notifyAll() 所有在對象O上wait的線程全部喚醒(應用較多)

 

4、如何停止一個線程

1、run方法代碼執行完成

2、線程運行時拋出一個未捕獲的異常,跳出線程

3、通過標誌位跳出線程

4、interrupt() 向需要中斷的線程發送停止指令;isInterrupted() 線程檢查自己的中斷標誌位;Thread.interrupted() 將中斷標誌位復位爲false;

 

不安全方式

Stop() 立刻停止線程,但不會釋放線程運行所應用的資源

Suspend() 立刻掛起線程,但不會釋放線程運行鎖應用的資源,容易造成死鎖

 

5、volatile關鍵字

在多個線程之間,訪問同一個被volatile修飾的對象時,所有線程共享這個對象的值。

但是volatile不是線程安全的(多個線程同時修改這個變量時,最終結果不一定是最後修改的那個值;可以保證線程的可見性,不可以保證操作的原子性)

 

6、synchronized如何使用

加鎖

可以修飾方法或代碼塊以同步的方式執行(同一時間只會有一個線程執行)

 

類鎖與實例鎖本質上是兩把鎖,類鎖鎖的是每一個類的class對象。

 

7、synchronized和Lock的區別

synchronized是一個Java的關鍵字,Lock是一個接口;

synchronized代碼塊執行完或線程拋出異常時結束線程,Lock必須顯示調用釋放鎖的方法:unlock();

synchronized修飾的鎖其他線程在等待獲取鎖的階段,會一直阻塞等待直到得到鎖爲止(不可中斷鎖);Lock有多種方式可以獲取鎖,不一定一直阻塞等待(可中斷鎖)。

synchronized無法判斷鎖的狀態,Lock可以判斷;

synchronized是非公平鎖,而Lock可以設置爲公平鎖;

 

Lock用法:

lock()(阻塞線程等待獲取鎖)

lockInterruptibly():可中斷(阻塞線程等待獲取鎖,會響應中斷)

tryLock():嘗試非阻塞的獲取鎖(非阻塞方式嘗試獲取鎖,無法獲取則返回false)

unlock()

 

公平鎖與非公平鎖:

公平鎖,先對鎖發出獲取請求的一定先獲得鎖。非公平鎖則反之(性能更高)。

ReentrantLock(boolean)可選擇公平鎖或非公平鎖,默認使用非公平鎖。

 

鎖的可重入:

遞歸的時候發生鎖的重入

synchronized隱式支持鎖的重入

ReentrantLock的lock()支持鎖的重入

 

排它鎖:同一時刻只有一個線程獲取鎖;

讀寫鎖:同一時刻運行多個讀線程訪問,但是隻允許一個寫線程,寫鎖會阻塞所有鎖。(ReentrantReadWriteLock,相比synchronized速度更快)

 

Condition接口有何作用?

Condition接口與Lock配合,來實現等待通知機制。

 

8、什麼是線程安全

當多個線程訪問某個類時,這個類始終都能表現出正確的行爲,那麼就稱這個類是線程安全的。

 

9、死鎖

當一個鎖未被釋放,其他線程無法獲取鎖的時候,程序產生死鎖情況。

 

死鎖的兩種情況:

1、線程thread1先獲取鎖locka,然後在同步塊裏嵌套競爭鎖lockb。而線程thread2先獲取鎖lockb,然後在同步塊裏嵌套競爭鎖locka。

2、Lock.unlock()方法的錯誤使用,導致死鎖。

 

10、Java線程池

什麼是線程池?用於管理線程的一個工具。

線程池的作用?限制系統中執行線程的數量;降低資源的消耗、提高響應速度、提高線程的可管理性。

 

Java常見的線程池:

Executors.newSingleThreadExecutor:單個線程的線程池;

Executors.newFixedThreadExecutor:固定線程數量的線程池;

Executors.newCacheThreadExecutor:可緩存線程;

Executors.newScheduledThreadPool:創建一個定長線程池,支持定時和週期性的執行線程;

 

11、併發工具類和併發容器類

常用的併發工具類:

閉鎖:CountDownLatch

柵欄:CyclicBarrier

信號量:Semaphore

交換者:Exchanger

 

CountDownLatch 閉鎖允許一個線程或多個線程等待特定情況,同步完成線程中其他任務。

 

CyclicBarrier和CountDownLatch都可以協同多個線程,讓指定數量的線程等待期他所有的線程都滿足某些條件之後才繼續執行。CyclicBarrier可以重複使用(reset),而CountDownLatch只能夠使用一次,如果還需要使用,必須重現new一個CountDownLatch對象。

構造方法CyclicBarrier(int, Runnable) 所有線程達到屏障後,執行Runnable。

 

Semaphore 型號量用來控制同時訪問特定資源的線程數量。

 

Exchanger 交換者用於在兩個線程之間傳輸數據,被調用後等待另一個線程達到交換點,然後相互交互數據。

 

常用的併發容器:

ConcurrentHashMap:JDK1.7實現:分段鎖;JDK1.8實現:元素(key)鎖+鏈表+紅黑樹

 

SkipList:跳錶自動隨機維護一套索引,用於高效的索引List中的有序數據。

CF81E54F072E454985A127FEC89BCE13uploading.4e448015.gif轉存失敗重新上傳取消

 

ConcurrentSkipListMap:TreeMap的併發實現

ConcurrentSkipListSet:TreeSet的併發實現

ConcurrentLinkedQueue:LinkedList的併發實現

CopyOnWriteArrayList:寫時複製,在添加元素是,複製一個新的容器,在新容器中新增元素;讀數據都在Old容器中操作,進行讀寫分離。數據一致性較弱,適合讀多寫少的場景。

CopyOnWriteArraySet:同上

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章