面試專題(Java基礎)

面向對象

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

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

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

 

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

 

2.四個基本特性安全

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

封裝:封裝將數據以及加在這些數據上的操做組織在一塊兒,提供給可信的其餘類或對象操做。併發

繼承:繼承就是從通常到特殊的過程。經過繼承能夠擁有現有類的全部功能,並在無需重修編寫原來類的狀況下對這些功能進行擴展。異步

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

 

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

 

3.抽象類和接口的區別

相同點:

都是上層的抽象;

都不能被實例化;

都能包含抽象方法。

不一樣點:

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

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

 

4.訪問控制符

private:同類可見

default:同包可見

protected:同包可見,子類可見

public:全局可見

 

5.重載和重寫

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

 

6.構造器Constructor是否可被override

構造器不容許被重寫。

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

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

 

語言特性

1.自動裝箱與拆箱

以問題引入:

JDK實際編譯的代碼:

將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 閉鎖容許一個線程或多個線程等待特定狀況,同步完成線程中其餘任務。

 

CyclicBarrierCountDownLatch均可以協同多個線程,讓指定數量的線程等待期他全部的線程都知足某些條件以後才繼續執行。CyclicBarrier能夠重複使用(reset),而CountDownLatch只可以使用一次,若是還須要使用,必須重現new一個CountDownLatch對象。

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

 

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

 

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

 

經常使用的併發容器

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

 

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

ConcurrentSkipListMap:TreeMap的併發實現

ConcurrentSkipListSet:TreeSet的併發實現

ConcurrentLinkedQueue:LinkedList的併發實現

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

CopyOnWriteArraySet:同上

相關文章
相關標籤/搜索