Java常見的一些經典面試題(附答案解析)

前言:

我想每個程式設計師比較頭疼的事情都是:工作擰螺絲,面試造火箭吧。但是又必須經歷這個過程,尤其是弄不清面試官問的問題,如果你準備的不是很充分,會導致面試的時候手足無措。今天這篇文章是從已工作5年的程式設計師面試幾十次中挑選的面試概率比較大的一些題目,都是大家被問到過的(就是這麼自信),希望這篇文章能夠對大家找工作有所幫助。

 

 

基礎部分

一丶抽象類和介面的區別
1.語法區別
(1)抽象類可以有構造方法,介面不能有構造方法;
(2)抽象類中可以有普通成員變數,介面中沒有普通成員變數;
(3)抽象類中可以有非抽象的方法,介面中的方法都必須是抽象的;
(4)抽象類中的方法可以是public,protected類型,介面中的方法只能是public類型的,切 默認為public abstract類型;
(5)抽象類中可以有靜態方法,介面中不能有靜態方法;
(6)抽象類中的靜態變數訪問類型可以是任意的,但介面中的靜態變數只能是public static final 類型。
(7).一個類可以實現多個介面,但一個類只能繼承一個抽象類;

2.應用區別
介面更多是在系統架構方面發揮作用,主要用於定義模組之間的通訊契約;而抽象類在程式碼方法 發揮作用,可以使用程式碼塊的重用;

二丶Java中介面可不可以繼承一般類,為什麼?
不可以因為介面中只能出現3種成員
1.公共的靜態常量(public static final )
2.公共的抽象方法(public abstract )
3.靜態內部類(static class)
而一個類中,就算什麼都不寫,也必須帶一個構造方法,在extends時就會被子類繼承,如果是介面也會 繼承這個構造方法,很明顯構造方法不在上面三項之列
而如果類中有一般的方法和成員變數,也會被子類全部繼承,這些更不能出現在介面中了,所以介面是絕 對不可能繼承一個類的

三、基本數據類型的默認值?基本數據類型所佔的位元組
1. 默認值
(1)byte、short、int、long的默認值為0
(2)float、double默認值為0.0
(3)char默認值為空
(4)boolean默認值為false
2.所佔位元組
(1)byte 1個位元組
(2)short 2個位元組
(3)char 2個位元組
(4)int 4個位元組
(5)long 8個位元組
(6)float 4個位元組
(7)double 8個位元組

四丶String屬於那個類,以及常用的方法
1.java.lang.string
2.substring(),indexOf(),concat(),endswith(),length(),replace()

五丶熟悉的網路協議
1.TCP/IP協議是一種面向連接的、可靠的協議。

TCP/IP協議中的四層分別是應用層、傳輸層、網路層和鏈路層,每層分別負責不同的通訊功能,接下來針對這四層進行詳細地講解。

鏈路層:用於定義物理傳輸通道,通常是對某些網路連接設備的驅動協議,例如針對光纖、網線提供的驅動。

網路層:網路層是整個TCP/IP協議的核心,它主要用於將傳輸的數據進行分組,將分組數據發送到目標電腦或者網路。

傳輸層:主要使網路程式進行通訊,在進行網路通訊時,可以採用TCP協議,也可以採用UDP協議。

應用層:主要負責應用程式的協議,例如HTTP協議、FTP協議等。
2.FTP 文件傳輸協議,允許在網路上傳輸文件。

六、String、StringBuffer、StringBuilder

String的值是不可改變的,這就導致每次對String的操作都會生成新的String對象,不禁效率底下, 而且浪費大量的記憶體空間;StringBuilder是可變類,任何對他指向的字元串的操作都不會產生新的對 象,但單執行緒不安全;StringBuffer底層方法使用了synchronized關鍵字,執行緒比較安全,但效率 較StringBuilder慢;

七、設計模式
單例模式:某個類只能有一個實例,提供一個全局的訪問點;
工廠模式:定義一個創建對象的介面,讓子類決定實例化那個類;
代理模式:為其他對象提供一個代理以便控制這個對象的訪問;

八、高並發如何處理?
1.從最基礎的地方做起,優化我們寫的程式碼,減少必要的資源浪費。
a.避免頻繁的new對象,對於整個程式只需要一個實例的類,我們可以使用單例模式;對於String 鏈接操作,使用StringBuffer或StringBuilder,對於工具類可以通過靜態方法來訪問;
b.避免使用錯誤的方式,使用java中高效率的類,比如ArrayList比Vector性能好;
2.html靜態化
把一些經常不改變的內容靜態化,高並發時減少伺服器的壓力;
3.圖片伺服器分離
對於web伺服器來說,圖片是最消耗資源的,於是我們把圖片放到獨立的伺服器,這樣可以降低 頁面請求伺服器的系統壓力;
4.快取
避免每一次都去資料庫中去查詢,減少資料庫的訪問量;並且使用redis資料庫來做快取,它的 讀寫速度是非常快的;
5.資料庫優化
(1)優化sql語句
a.Select語句必須指定列名
b.當查詢結果為一條時,使用limit 1
c.避免使用%前綴搜索,避免全表掃描

九、get與post的區別
GET在瀏覽器回退時是無害的,而POST會再次提交請求。 GET產生的URL地址可以被Bookmark,而POST不可以。 GET請求會被瀏覽器主動cache,而POST不會,除非手動設GET請求只能進行url編碼,而POST支援多種編碼方式。 GET請求參數會被完整保留在瀏覽器歷史記錄里,而POST中的參數不會被保留。 GET請求在URL中傳送的參數是有長度限制的,而POST么有。 對參數的數據類型,GET只接受ASCII字元,而POST沒有限制。 GET比POST更不安全,因為參數直接暴露在URL上,所以不能用來傳遞敏感資訊。 GET參數通過URL傳遞,POST放在Request body中。

十、JDK1.8新特性

  1. 提供lambda表達式極大地減少了程式碼的冗餘;
  2. 在介面中可以使用default和static關鍵字來修飾介面中的普通方法;
  3. 提供新的API LocalDate | LocalTime | LocalDateTime
    (1)Java.util.Date和SimpleDateFormatter執行緒上都不安全,而LocalDate和LocalTime和 String一樣都是不可改變類,執行緒上比較安全,還不能修改;
    (2)Java.util.Date月份從0開始,12月是11,而java.time.LocalDate月份和星期都改成了 enum, 就不可能出錯了;

集合部分

一、List、Map、Set三個介面,存取元素時,各有什麼特點
(1)Set集合的add有一個boolean類型的返回值,當集合中沒有某個元素時,則可以成功加入該 元素,返回結果為true;當集合中存在與某個元素equals方法相等 的元素時,則無法加入該元素, 取元素時只能用Iterator介面取得所有元素,在逐一遍歷各個元素;
(2)List表示有先後順序的集合,調用add()方法,指定當前對象在集合中的存放位置;一個對象可 以被反覆存進集合中;每調用一次add()方法,該對象就會被插入集合中一次,其實,並不是把對 象本身存進了集合中,而是在集合中使用一個索引變數指向了該對象,當一個對象被add多次時, 即有多個索引指向了這個對象。List去元素時可以使用Iterator取出所有元素,在逐一遍歷,還可 以使用get(int index)獲取指定下表的元素;
(3)Map是雙列元素的集合,調用put(key,value),要存儲一對key/value,不能存儲重複的key, 這個是根據eauals來判斷;取元素時用get(key)來獲取key所對 應的value,另外還可以獲取 全部key,全部value

二、ArrayList和LinkedList的底層實現原理?他們為什麼執行緒不安全?在多執行緒並發操作下,我們應該用什麼替代?
1.ArrayList底層通過數組實現,ArrayList允許按序號索引元素,而插入元素需要對數組進行移位等記憶體操作,所以索引快插入較慢;(擴容方式)一旦我們實例化了ArrayList 無參構造函數默認數組長度為10。add方法底層如 果增加的元素超過了10個,那麼ArrayList底層會生成一個新的數組,長度為原來數組長度的1.5倍+1,然後將原數組內容複製到新數組中,並且後續加的內容都會放到新數組中。當新數組無法容納增加元素時,重複該過程;

2.LinkedList底層通過雙向鏈表實現,取元素時需要進行前項或後項的遍歷,插入元素時只需要記錄本項的前後 項即可,所以插入快查詢慢;

3.ArrayList和LinkedList底層方法都沒有加synchronized關鍵詞,多執行緒訪問時會出現多個執行緒先後更改數據造成得到的數據是臟數據;多執行緒並發操作下使用Vector來代替,Vector底層也是數組,但底層方法都加synchronized關鍵字使執行緒安全,效率較ArrayList差;

三、HashMap和HashTable有什麼區別?其底層實現是什麼?CurrentHashMap的鎖機制又是如何?如果想將一個Map變為有序的,該如何實現?

1.區別:
(1)HashMap沒有實現synchronized執行緒非安全,HashTable實現了synchronized執行緒安全;
(2)HashMap允許key和value為null,而HashTable不允許

2.底層原理:數組+鏈表實現

3.ConcurrentHashMap鎖分段技術:HashTable效率低下的原因,是因為所訪問HashTable的執行緒都必須競爭同一把鎖,那假如容器中有多把鎖,每一把鎖用於鎖住容器中的一部分數據,那麼當多執行緒訪問容器中不同的數據時,執行緒間就不會存在鎖競爭,從而提高並發訪問率;ConcurrentHashMap使用的就是鎖分段技術,首先將數據分成一段一段的存儲,然後給每一段數據配一把鎖,當一個執行緒佔用鎖訪問其中一個數據時,其他段的數據也能被其他執行緒訪問;

4.實現TreeMap

框架部分

一、什麼是Spring
Spring是一個輕量級的開源框架,是為了解決企業應用開發的複雜性而創建的;提供IOC來幫住我們創建對象及管理對象之間的依賴關係,提供AOP來幫我們完成日誌的列印、異常的處理、事物的管理等操作,提供JDBC、ORM來完成持久層的操作,內置SpringMvc控制層框架

二、spring優點
1:方便解耦,簡化開發;
2:方便的對程式進行攔截、運行、監控等功能;
3:提供聲明式事物;
4:屬於一個萬能的框架,跟很多框架都是百搭;

三、什麼是IOC?什麼是AOP?
(1)IOC稱為控制反轉是指在程式運行時自動注入依賴對象;
底層實現原理:反射機制
(2)AOP稱為面向切面編程,就是程式中有很多各不想乾的方法,在這些方法中加入
某種系統功能的程式碼;例如加入日誌、加入異常處理、加入事物管理
底層實現原理:動態代理

四、反射機制:在程式運行時根據指定的類名獲取類的資訊;
主要作用:
1.在運行時構造一個類的對象;
2.判斷一個類所具有成員變數和方法;
3.調用一個對象的方法;
4.生成動態代理;

五、動態代理:利用Java反射技術,在運行時創建一個實現某些給定介面的新類(又分為JDK動態代理和Cglib動態代理)
主要作用:
1.可以隱藏委託類(就是被代理類)的具體實現
2.可以實現客戶與委託類間的解耦,再不修改委託類程式碼的情況下能夠做一些額外的處理
JDK動態代理和Cglib動態代理的區別?
JDK動態代理只能對實現了介面的類生成代理,為不能針對類
Cglib動態代理是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法(集成)

六、什麼是DI機制?
依賴注入(Dependecy Injection)和控制反轉(Inversion of Control)是同一個概念,具體的講:當某個角色需要另外一個角色協助的時候,在傳統的程式設計過程中,通常由調用者來創建被調用者的實例。但在spring中創建被調用者的工作不再由調用者來完成,因此稱為控制反轉。創建被調用者的工作由spring來完成,然後注入調用者,因此稱為依賴注入;

七、Spring的Ioc注入方式有幾種?
一、Set注入
二、構造器注入
三、介面注入
spring注入方便管理,依賴注入或者說是控制反轉,說白了就是使用了配置文件,這種思想的唯一好處就是增加了模組的重用性靈活性。

八、hibernate的工作原理
1.通過Configuration().configure();讀取並解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.xml中的讀取並解析映射資訊
3.通過config.buildSessionFactory();//創建SessionFactory
4.sessionFactory.openSession();//打開Sesssion
5.session.beginTransaction();//創建事務Transation
6.persistent operate持久化操作
7.session.getTransaction().commit();//提交事務
8.關閉Session
9.關閉SesstionFactory

九、hibernate優點:
1.對JDBC訪問資料庫的程式碼做了封裝,大大簡化了數據訪問層繁瑣的重複性程式碼。
2.Hibernate是一個基於JDBC的主流持久化框架,是一個優秀的ORM實現。他很大程度的簡化DAO 層的編碼工作
3.hibernate使用Java反射機制,而不是位元組碼增強程式來實現透明性。
4.hibernate的性能非常好,因為它是個輕量級框架。映射的靈活性很出色。它支援各種關係資料庫, 從一對一到多對多的各種複雜關係。

十、SpringMvc運行流程
1.用戶發送請求到DispatchServlet
2.DispatchServlet根據請求路徑查詢具體的Handler
3.DispatchServlet調用HandlerAdapter適配器,適配器再調用具體的Handler處理業務
4.Handler處理結束返回一個具體的ModelAndView給適配器,適配器將ModelAndView給 DispatchServlet
5.DispatchServlet把視圖名稱給ViewResolver視圖解析器
6.ViewResolver視圖解析器返回一個具體視圖給DispatchServlet
7.將渲染視圖的展示給用戶

十一、ssh和是ssm的區別
SSH 通常指的是 Struts2 做控制器(controller),spring管理各層的組件,hibernate 負責持久化層。
SSM 則指的是 SpringMVC 做控制器(controller),Spring 管理各層的組件,MyBatis 負責持久化 層。
共同點:
1.Spring依賴注入DI來管理各層的組件。
2.使用面向切面編程AOP管理事物、日誌、許可權等。
不同點:
1.struts2和springmvc的區別;
2.hibernate和mybatis的區別;

十二、struts2和SpringMvc的區別?
1.springmvc入口是一個servlet前段控制器,struts2入口是一個filter過濾器;
2.springmvc是基於方法開發的,傳遞參數通過方法的形參來傳遞;struts2是基於類開發的,傳遞參 數通過類的屬性來傳遞;
3.SpringMvc通過參數綁定期將request請求內容解析,並給方法形參賦值;struts2採用值棧存儲 請求和響應數據,通過OGNL存儲數據;

十三、hibernate和Mybatis的區別?
屏蔽jdbc的底層訪問細節,使我們不與jdbc api打交道,就可以訪問數據;jdbc api編程流程固定,還將sql語句與java程式碼混雜在了一起,經常需要拼湊sql語句,細節很繁 瑣;iBatis提供了自動將結果集封裝成實體對象和對象集合的功能,queryForList返回對象集合,用queryForObject返回單個對象,提供了將實體對象的屬性傳遞給sql語句的參數;Hibernate是一個全自動的orm映射工具,他可以自動生成sql語句,ibatis需要我們自己在xml配置文件中寫sql語句,hibernate要不ibatis負責功能強大很多。因為hibernate自動生成sql語句,不能寫高效率的sql語句,對於一些不太複雜的sql查詢hibernate可以很好的幫我們完成,特別複雜查詢ibatis就比較合適了;

十四、Mybatis快取機制?
快取機制:Mybatis首先去快取中查詢結果集,如果沒有則查詢資料庫,如果有則從快取中取出返回結果集就不走資料庫;
Mybatis的一級快取是SqlSession級別的快取,在操作資料庫時需要創建SqlSession對象,在對象中有一個數據結構用於存儲快取的數據,不同的SqlSession之間的快取互不影響並且不能互相讀取;
Mybatis的二級快取即查詢快取,它的作用域是一個mapper的namespace,即在同一個namespace中查詢sql可以從快取中獲取數據,二級快取是可以跨 SqlSession的;
MyBatis 默認沒有開啟二級快取,開啟只需在配置文件中寫入如下程式碼:

<settings>  
            <setting name="cacheEnabled" value="true"/>
    </settings>

Web部分

一、JSP九大內置對象?作用分別是什麼?分別有什麼方法

request:用戶端請求,此請求會包含來自GET/POST請求的參數
response:網頁傳回用戶端的回應
pageContext:網頁的屬性是在這裡管理
session:與請求有關的回話期
application servlet:正在執行的內容
out:用來傳送回應的輸出
page:JSP網頁本身
config:servlet的構架部分
exception:針對錯誤網頁,未捕捉的例外
request表示HttpServletRequest對象;它包含了有關瀏覽器請求的資訊,並且提供了幾個用於獲取cookie,header和session數據的方法
response表示HttpServletResponse對象,並且提供了幾個用於設置送回瀏覽器響應的方法

二、forward()與redirect()的區別?
forward是容器中控制權的轉向,在客戶端瀏覽器不會顯示轉向後的地址;redirect則是完全的跳轉,瀏覽器將會得到跳轉的地址,並重新發送請求鏈接,這樣瀏覽器地址欄中就可以看到跳轉後的鏈接地址。所以forward更加高效,在forward能滿足需要時,盡量使用forward並且有助於隱藏實際的鏈接。如需要跳轉到一個其他伺服器上的資源,則必須使用redirect;

執行緒部分

1. 程式,進程,執行緒這三者之間的關係?

一個程式中可以調用多個進程,一個進程中可以有多個執行緒;比如一個影片播放器,裡面就有兩個進程:一個是播放影片的進程,一個是下載上傳影片的進程;多個用戶看影片就是多個執行緒訪問一個進程;

2.單執行緒與多執行緒區別,以及多執行緒意義?

如果程式只有一條執行路徑,這就是單執行緒;相反如果有多條路徑,那就是多執行緒;
多執行緒的意義他可以讓程式在一個時間執行多個事情,提高了應用程式的使用率;

3.理解並發與並行

並發:通過CPU調度演算法,讓用戶看上去同時執行,實際上,是通過CPU再高速切換,並不是真正的同時,這就是並發;
並行:多個CPU實例或者多台機器同時執行一段邏輯,這就是真正的同時,這就是並行;

4.如何創建執行緒
方法一:
(1)類去繼承Thread類;
(2)該類重寫Thread類的run方法,並且將執行緒要執行的程式碼,存放到run方法中;
(3)執行緒對象調用start()方法,開啟執行緒,執行緒會自動執行run方法
方法二
(1)類繼承Runnable介面
(2)重寫介面run方法,並將執行緒執行程式碼存放在run方法中
(3)創建Thread對象,也就是創建執行緒
(4)Thread執行緒對象調用start方法,啟動執行緒

5.執行緒的幾種狀態?
初始化(new Thread()) –> 就緒(start()準備執行) –> 執行(獲得CPU執行權)
執行1 –> 等待(wait()):執行緒處於等待狀態,自己醒不了,只能用notify()或notifyAll()喚醒,處於等待狀態的執行緒會釋放CPU執行權,同時釋放資源;
執行2 –> 睡眠(sleep()):在指定毫秒數內讓當前正字執行的執行緒休眠,只是暫停執行,他會釋放CPU執行權,但不會釋放資源,設定時間到了,就會脫離睡眠狀態,進入執行狀態;
執行3 –> 阻塞:當多條執行緒存在輸入輸出時,就會出現阻塞狀態
執行4 –> 死亡:run方法執行完畢,執行緒結束了也就是處於死亡狀態

6.多執行緒解決方法
(1)同步程式碼塊:程式碼塊放入同步鎖中
(2)同步方法:方法前加synchronized關鍵字

7.什麼是死鎖(deadlock)?
兩個進程都在等待對象執行完後才繼續往下執行的時候就發生了死鎖,兩個進程都陷入了無限的等待中;

資料庫

一、你所了解的資料庫優化方面有哪些?
1.Select語句必須指定欄位名稱
2.當只查詢結果為一條數據時,使用limit 1
3.避免where子句對欄位進行null值判斷(對於null的判斷會導致引擎放棄使用索引而進行全表掃描)
4.不建議使用%前綴模糊查詢,防止全表掃描

二、事務的四大特徵
1.原子性(Atomicity)
原子性是指事務包含的所有操作要麼全部成功,要麼全部失敗回滾;
2.一致性(Consistency)
也就是說一個事物執行之前和執行之後都必須處於一致性狀態;那轉賬來說,假設A和B兩者的 錢一共是5000,不管A和B之間如何轉賬,轉幾次賬,事務結束後兩人的錢加起來還是5000,這就 是事務的一致性;
3.隔離性
隔離性當多個用戶並發訪問資料庫並操作同一張表時,資料庫為每一個用戶開啟的事務,不能被 其他事務操作所干擾,多個並發事務之間要相互隔離;比如兩個並發事務T1和T2,在事務T1看來, T2要麼在T1開始前結束事務,要麼在T1結束後開始事務,這就是事務的隔離性;
4.持久性
執行性是指一個事務一但被提交了,那麼對資料庫中的數據的改變就是永久性的;

三、Spring隔離級別

  1. 如果多個事務同時訪問相同數據時,如果沒有採取必要的隔離級別,可能會發生什麼問題?
    (1)臟讀:讀取過期的數據,就是一個事物讀到另一個事務未提交的新數據;
    (2)幻讀:讀取臨時的數據,就是一個事物在進行修改全表的時候,另一個事務對數據進行了新 增,從而第一個事務的執行完後發現還有沒有修改的數據,就好像發生了幻覺一樣;
    (3)不可重複讀:就是在同一個事務中先後執行兩條一樣的select語句,之間沒有執行過Del 語句但先後結果不一樣,這就是不可重複讀;
  2. Spring事務隔離級別
    (1) Default:使用資料庫本身的隔離級別ORACLE(讀已提交)Mysql(可重複讀);
    (2) Read_Uncomited:讀未提交(臟讀),最低隔離級別,一切皆有可能;
    (3) Read_Commited:讀已提交,有幻讀以及不可重複讀的風險;
    (4) RepeaTable_Read:可重複讀,但還是有幻讀風險;
    (5) Serializable:串列化,最高隔離界別,杜絕一切隱患,但效率較低;

四、Spring怎麼設置隔離級別?

  1. 用@Transactional註解聲明式事務的事務管理中來設置isolation屬性的隔離級別
  2. 在配置文件中設置事務tx:method元素

伺服器

Nginx是一款輕量級的Web 伺服器/反向代理伺服器及電子郵件(IMAP/POP3)代理伺服器,並在一個BSD-like 協議下發行。其特點是佔有記憶體少,並發能力強,

Keepalived的作用是檢測伺服器的狀態,如果有一台web伺服器宕機,或工作出現故障,Keepalived將檢測到,並將有故障的伺服器從系統中剔除,同時使用其他伺服器代替該伺服器的工作,當伺服器工作正常後Keepalived自動將伺服器加入到伺服器群中,這些工作全部自動完成,不需要人工干涉,需要人工做的只是修復故障的伺服器。

Redis

1. 設置快取值的過期時間?
(1) 常用的方式:expire key time(以秒為單位)
(2) 字元串獨有方式:setex(String key,int seconds,String value)
如果沒有設置時間,那快取就是永不過期;
2. Redis三種過期策略
(1)定時刪除:在設置key過期時間的同時,為該key創建一個定時器,讓定時器在key過期的時候,對key進行刪除;
(2)惰性刪除:key過期的時候不刪除,每次從資料庫獲取key的時候去檢查是否過期,若過期刪除,返回null;
(3)定期刪除:每隔一段時間執行一次刪除過期key的操作

總結:

針對於上面的面試題我總結出了互聯網公司java程式設計師面試涉及到的絕大部分面試題及答案做成了文檔和架構影片資料免費分享給大家(包括Dubbo、Redis、Netty、zookeeper、Spring cloud、分散式、高並發等架構技術資料),希望能幫助到您面試前的複習且找到一個好的工作,也節省大家在網上搜索資料的時間來學習,也可以關注我以後會有更多乾貨分享。