最近辭職準備面試,順便整理一下面試題分享給你們,若有錯誤歡迎指出java
01. 你對面向對象思想的理解?程序員
面向對象編程簡稱OOP,是開發程序的一種方法、思想。
面向過程編程中經常會致使全部的代碼都在一塊兒,難以閱讀和維護,牽一動百。而OOP,使用許多代碼模塊,每一個模塊都只提供特定的功能,彼此獨立,能夠增長代碼重用概率,更加有利於軟件的開發、維護和升級。
另外OOP的三大核心特性:繼承、封裝、多態 的特性,使得程序員可以設計出高內聚、低耦合的系統結構,使得系統更靈活、易擴展,成本較低面試
02. 不少程序員都知道多態,但大都知其然不知其因此然,說說你對多態的理解
一個引用變量倒底會指向哪一個類的實例對象,該引用變量發出的方法調用究竟是哪一個類中實現的方法,在編程時並不肯定,而是在程序運行期間才肯定。
由於在程序運行時才肯定具體的類,即不修改程序代碼就能夠改變程序運行時所綁定的具體代碼,讓程序能夠選擇多個運行狀態,這就是多態性
多態的優勢:解耦、靈活、可擴展性強算法
多態存在的三個必要條件:繼承、重寫、父類引用指向子類對象sql
03. Collection集合有什麼子類
List
1.能夠容許重複的對象。
2.能夠插入多個null元素。
3.有序,保持元素的插入順序
4.經常使用的實現類有 ArrayList、LinkedList 和 Vector。ArrayList 最爲流行,它提供了使用索引的隨意訪問,而 LinkedList 則對於常常須要從 List 中添加或刪除元素的場合更爲合適。數據庫
Set
1.不容許重複對象
2.無序
3.只容許一個 null 元素
4.Set 接口最流行的幾個實現類是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基於 HashMap 實現的 HashSet;TreeSet 還實現了 SortedSet 接口。編程
Map
1.Map不是collection的子接口或者實現類。Map是一個接口。
2.Map 可能會持有相同的值對象但鍵對象必須是惟一的。
3.TreeMap 也經過 Comparator 或者 Comparable 維護了一個排序順序。
4.Map 裏你能夠擁有隨意個 null 值但最多隻能有一個 null 鍵。
Map 接口最流行的幾個實現類是 HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最經常使用)vim
04. list,set,map的使用場景
1.若是你常常會使用索引來對容器中的元素進行訪問,那麼 List 是你的正確的選擇。若是你已經知道索引了的話,那麼 List 的實現類好比 ArrayList 能夠提供更快速的訪問,若是常常添加刪除元素的,那麼確定要選擇LinkedList。
2.若是你想容器中的元素可以按照它們插入的次序進行有序存儲,那麼仍是 List,由於 List 是一個有序容器,它按照插入順序進行存儲。
3.若是你想保證插入元素的惟一性,也就是你不想有重複值的出現,那麼能夠選擇一個 Set 的實現類,好比 HashSet、LinkedHashSet 或者 TreeSet。
4.若是你以鍵和值的形式進行數據存儲那麼 Map 是你正確的選擇。你能夠根據你的後續須要從 Hashtable、HashMap、TreeMap 中進行選擇。數組
05. ArrayList和HashMap的比較
使用場景:若是須要快速隨機訪問元素,應該使用ArrayList。須要鍵值對形式的數據時,應該使用HashMap瀏覽器
相同點:
1)都是線程不安全,不一樣步 2)均可以儲存null值 3)獲取元素個數方法同樣,都用size()方法獲取
區別:
1)實現的接口 ArrayList實現了List接口(Collection(接口)->List(接口)->ArrayList(類)),底層使用的是數組;而HashMap現了Map接口(Map(接口)->HashMap(類)),底層使用的是Hash算法存儲數據。 2)存儲元素 ArrayList以數組的方式存儲數據,裏面的元素是有順序,能夠重複的;而HashMap將數據以鍵值對的方式存儲,鍵的哈希碼(hashCode)不能夠相同,相同後面的值會將前面的值覆蓋,值能夠重複,裏面的元素無序。 3)添加元素的方法 ArrayList用add(Object object)方法添加元素,而HashMap用put(Object key, Object value)添加元素。 4)默認的大小和擴容 在 Java 7 中,ArrayList的默認大小是 10 個元素,HashMap 的默認大小是16個元素(必須是2的冪)。
06. 多線程建立方式有哪幾種(具體建立過程是什麼)
1.繼承thread 類,重寫run方法,而後new Thread().start啓動線程,也能夠直接匿名內部類的方式建立
new Thread(
public void run(){ };
).start;
在裏邊寫run方法的實現
2.實現runnable接口,重寫run方法
3.實現callable接口(通常不多用)
07. 多線程的常見應用場景:
一、後臺定時任務,例如:定時向大量(100w以上)的用戶發送郵件;
二、異步處理,例如:發微博、記錄日誌等;
三、分佈式計算消息隊列
08. 線程有哪幾種狀態
1.建立狀態 剛被new Thread()
2.就緒狀態 準備好了run方法,等待cpu
3.運行狀態 running
4.阻塞狀態(包括sleep、wait(notify)、suspend(resume)、以及沒搶到鎖)
5.死亡狀態
09. 線程池初始化時有哪些參數能夠設置
通常tomcat線程池不用本身配,本身寫線程池的話是須要本身配置參數的
那 線程初始化時設置參數的格式是:
private static final int corePoolSize = xxx;
建立線程池對象時,將配置的各類參數用逗號鏈接傳參進去。
ThreadPoolExecutor mExecute = new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, threadFactory, rejectHandler
);
各個參數表明的意義:
corePoolSize:線程池的核心線程數。在沒有設置 allowCoreThreadTimeOut 爲 true 的狀況下,核心線程會在線程池中一直存活,即便處於閒置狀態。 maximumPoolSize:線程池所能容納的最大線程數。大於這個數調用任務拒絕handler keepAliveTime:非核心線程閒置時的超時時長。超過該時長,非核心線程就會被回收。 unit:keepAliveTime 時長對應的單位。 workQueue:線程池中的任務隊列,當有提交的任務暫時沒有足夠的線程去執行的時候,就會進入workQueue等待 rejectHandler:拒絕策略,當線程池中線程數大於maximumPoolSize,且任務隊列也排滿了,如何拒絕任務。 JDK給咱們內置了四種拒絕策略:直接拋出異常、丟棄最老的一個任務而後從新提交當前任務、放棄沒法執行的任務,而後當作無事發生、還有一種沒看懂就不寫出來了
10. 線程池的種類(4種)區別和使用場景
首先,不一樣線程池之間的區別就是他們新建時傳入的參數值不同(新建方法是同樣的)
1.newFixedThreadPool,線程數量固定的線程池,線程池的corePoolSize和maximumPoolSize大小同樣,而且keepAliveTime爲0,傳入的隊列LinkedBlockingQueue爲無界隊列
2.newSingleThreadExecutor,單線程池,corePoolSize和maximumPoolSize都是1,keepAliveTime是0
3.newCachedThreadPool,可緩存線程池,說到緩存通常離不開過時時間,該線程池也是,corePoolSize設置爲0,maximumPoolSize設置爲int最大值,不一樣的是,線程池傳入的隊列是SynchronousQueue,一個同步隊列,該隊列沒有任何容量,每次插入新數據,必須等待消費完成。當有新任務到達時,線程池沒有線程則建立線程處理,處理完成後該線程緩存60秒,過時後回收,線程過時前有新任務到達時,則使用緩存的線程來處理。
4.newScheduledThreadPool,這個線程池使用了ScheduledThreadPoolExecutor,該線程池繼承自ThreadPoolExecutor, 執行任務的時候能夠指定延遲多少時間執行,或者週期性執行。
11. ==和equals有什麼區別?
對基本數據類型 ==比較的是值,引用類型 ==比較的是地址 equals比較的大可能是地址,可是String和Integer對其進行了重寫,因此比較的是值
12. Thread類中的start()和run()方法有什麼區別
start啓動線程,run方法只是thread的一個普通方法,就算調用了也仍是在主線程裏執行
同步有幾種實現方法?
同步的實現方面有兩種,使用synchronized同步鎖、volatile關鍵字、lock鎖對象的lock()和unlock()方法
volatile關鍵字
Java 語言中的 volatile 變量能夠被看做是一種 「程度較輕的 synchronized」
鎖提供了兩種主要特性:互斥(mutual exclusion) 和可見性(visibility)。
互斥指一個線程拿到了鎖,其餘線程就必須等待完成。
可見性要表示一個線程改完了一個公共數據(其實是先改本身的緩存數據,而後同步到公共數據上,而後另外的線程看到公共數據變了,將變換的值同步到本身的緩存,這個過程有好幾部,因此會有線程安全問題),必需要保證其餘線程知道數據改變了
使用 volatile 變量的主要緣由用法簡單,在公共數據上加一個volatile關鍵字就行,其次是性能優於sychronize同步鎖
線程產生死鎖的緣由和解決辦法:
什麼是死鎖:打個比方,假設有P1和P2兩個進程,都須要A和B兩個資源,如今P1持有A等待B資源,而P2持有B等待A資源,兩個都等待另外一個資源而不願釋放資源,就這樣無限等待中,這就造成死鎖
定義:若是一組進程中每個進程都在等待僅由該組進程中的其餘進程才能引起的事件,那麼該組進程是死鎖的。
產生死鎖緣由:一種緣由是系統提供的資源太少了,遠不能知足併發進程對資源的需求。這種競爭資源引發的死鎖是咱們要討論的核心;
另外一種緣由是因爲進程推動順序不合適引起的死鎖。資源少也未必必定產生死鎖。就如同兩我的過獨木橋,若是兩我的都要先過,在獨木橋上僵持不願後退,必然會應競爭資源產生死鎖;可是,若是兩我的上橋前先看一看有無對方的人在橋上,當無對方的人在橋上時本身才上橋,那麼問題就解決了。因此,若是程序設計得不合理,形成進程推動的順序不當,也會出現死鎖。
解決死鎖問題的三種方法:預防死鎖、檢測死鎖及避免死鎖。
解決辦法:預防死鎖的發生每每須要很大的系統開銷,並且不能充分利用資源,爲此,一種簡便的方法是系統爲進程分配資源時,不採起任何限制性措施,可是提供了檢測和解脫死鎖的手段
核心思想:打破線程間的相互等待狀態,好比
1.找到相互等待的線程的spid,kill掉
2.使用sql server 內部的鎖監視器線程執行死鎖檢查,當檢測到死鎖時,回滾事務以及該事務持有的鎖,使得其餘線程得以正常運行
多線程有幾種實現方法?
多線程有三種實現方法,分別是繼承Thread類、實現Runnable接口、實現Callable接口
Callable和Runnable的區別是什麼
(1)Callable規定的方法是call(),Runnable規定的方法是run().
(2)Callable的任務執行後可返回值,而Runnable的任務是不能返回值得
(3)call方法能夠拋出異常,run方法不能夠
(4)運行Callable任務能夠拿到一個Future對象,Future 表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並獲取計算的結果。計算完成後只能使用 get 方法來獲取結果,若是線程沒有執行完,Future.get()方法可能會阻塞當前線程的執行;若是線程出現異常,Future.get()會throws InterruptedException或者ExecutionException;若是線程已經取消,會跑出CancellationException。取消由cancel 方法來執行。isDone肯定任務是正常完成仍是被取消了。一旦計算完成,就不能再取消計算。若是爲了可取消性而使用 Future 但又不提供可用的結果,則能夠聲明Future<?> 形式類型、並返回 null 做爲底層任務的結果。
IO流,瞭解常見的幾個流對象以及基本的流操做便可
數組集合
什麼是鏈接池,爲何使用鏈接池
什麼是接口隔離?
接口跟抽象類的區別?
hashcode和equal的區別
hashmap和hashtable的區別是什麼?
hashmap實現原理,擴容因子過大太小的缺點,擴容過程
ArrayList和linkenList的區別?
java地址和值傳遞的例子
值傳遞:只傳遞值,各是各的
引用傳遞:傳遞地址,共同操做這個值
Linux經常使用命令列舉10個
ls/ll 顯示文件夾下全部文件/詳細顯示
pwd 查看當前目錄的絕對路徑
cd 切換目錄
ps 查看進程
kill 殺死進程
mv 移動文件
mkdir 建立文件夾
rmdir 刪除文件夾
touch 建立文件
tar zxvf 解壓
date 顯示日期
cal 顯示日曆
vi 用vim編輯文件
clear 清屏
synchronized實現原理
synchronizated和lock差異?
java Nio
是否能夠繼承String類?
String類是final類故不能夠繼承。
幾種線程暫停
a. wait():使一個線程處於等待狀態,而且釋放持有的鎖
b. sleep():使一個正在運行的線程處於睡眠狀態,時間過了自動會醒,因此不釋放鎖
c. notify():喚醒一個處於等待狀態的線程,注意的是在調用此方法的時候,並不能確
切的喚醒某一個等待狀態的線程,而是由JVM肯定喚醒哪一個線程,並且不是按優先級。
d. allnotity():喚醒全部處入等待狀態的線程,注意並非給全部喚醒線程一個對象的鎖,而是讓它們競爭。
啓動一個線程是用run()仍是start()?
啓動一個線程是調用start()方法,使線程就緒狀態,之後能夠被調度爲運行狀態,一個線程必須關聯一些具體的執行代碼,run()方法是該線程所關聯的執行代碼。
SOCKET套接字中有幾中鏈接方式,各有什麼區別?
Sockets有兩種主要的操做方式:面向鏈接(TCP/IP)的和無鏈接(UDP)的。無鏈接的操做使用數據報協議,無鏈接的操做是快速的和高效的,可是數據安全性不佳. 面向鏈接的操做使用TCP協議.面向鏈接的操做比無鏈接的操做效率更低,可是數據的安全性更高
sleep()和wait()區別
sleep() 方法:線程主動放棄CPU,使得線程在指定的時間內進入阻塞狀態,不能獲得CPU 時間,指定的時間一過,線程從新進入可執行狀態。典型地,sleep() 被用在等待某個資源就緒的情形:測試發現條件不知足後,讓線程阻塞一段時間後從新測試,直到條件知足爲止。
wait( ) :與notify()配套使用,wait()使得線程進入阻塞狀態,它有兩種形式,一種容許指定以毫秒爲單位的一段時間做爲參數,另外一種沒有參數,當指定時間參數時對應的 notify() 被調用或者超出指定時間時線程從新進入可執行狀態,後者則必須對應的 notify() 被調用
hashCode方法的做用?
hashcode這個方法是用來鑑定2個對象是否相等的。hashcode方法通常用戶不會去調用,好比在hashmap中,因爲key是不能夠重複的,他在判斷key是否是重複的時候就判斷了hashcode這個方法,並且也用到了equals方法。這裏不能夠重複是說equals和hashcode只要有一個不等就能夠了!因此簡單來說,hashcode至關因而一個對象的編碼。咱們通常在覆蓋equals的同時也要覆蓋hashcode,讓他們的邏輯一致。
簡述synchronized和java.util.concurrent.locks.Lock的異同 ?
主要相同點:Lock能完成synchronized所實現的全部功能
主要不一樣點:Lock有比synchronized更精確的線程語義和更好的性能。synchronized會自動釋放鎖,而Lock必定要求程序員手工釋放,而且必須在finally從句中釋放。Lock還有更強大的功能,例如,它的tryLock方法能夠非阻塞方式去拿鎖。
Java字節碼的執行有兩種方式:
1)即時編譯方式:解釋器先將字節編譯成機器碼,而後再執行該機器碼。 2)解釋執行方式:解釋器經過每次解釋並執行一小段代碼來完成java字節 碼程序的全部操做。
Java四種引用包括強引用,軟引用,弱引用,虛引用
2.獲取Class的方式有哪些
方式一:對象.getClass()
Student student = new Student();
student.getClass();
方式二:類名.Class
Student.Class
方式三:Class.forname("完整的類路徑.包名.類名")
3.int和Integer的區別
基礎答案:Ingeter是int的包裝類,int的初值爲0,Ingeter的初值爲null。
進階答案:Ingeter將-128-127進行緩存,所以
4.ArrayList和LinkedList的區別
1.ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。
2.對於隨機訪問get和set,ArrayList以爲優於LinkedList,由於LinkedList要移動指針。
3.對於新增和刪除操做add和remove,LinedList比較佔優點,由於ArrayList要移動數據。
5.==和equals的區別
1)對於==,比較的是值是否相等
若是做用於基本數據類型的變量,則直接比較其存儲的 「值」是否相等;
若是做用於引用類型的變量,則比較的是所指向的對象的地址
2)對於equals方法,注意:equals方法不能做用於基本數據類型的變量
若是沒有對equals方法進行重寫,則比較的是引用類型的變量所指向的對象的地址;
諸如String、Date等類對equals方法進行了重寫的話,比較的是所指向的對象的內容。
6.override和overload的比較
重載Overload:在同一個類中,容許存在一個以上的同名函數,只要他們的參數個數或者參數類型不一樣便可。
重載的特色:與返回值類型無關,只看參數列表。
重寫Override表示子類中的方法能夠與父類中的某個方法的名稱和參數徹底相同,經過子類建立的實例對象調用這個方法時,將調用子類中定義的方法,這至關於把父類中定義的那個徹底相同的方法給覆蓋掉了,這也是面向對象編程的多態的一種表現。子類覆蓋父類方法時只能拋出父類的異常或者異常的子類或者父類異常的子集,由於子類能夠解決父類的一些問題,但不能比父類有更多的問題。還有,子類方法的訪問權限只能比父類的更大,不能更小。若是父類的方法是private類型,則子類中根本不存在覆蓋,即子類中和父類的private的同名的方法沒有覆蓋的關係,由於private的訪問權限只限於同一類中,而子類就不會訪問到private的方法,因此是子類中增長的一個全新的方法
7.簡述servlet生命週期
(1)加載和實例化
當Servlet容器啓動或客戶端發送一個請求時,Servlet容器會查找內存中是否存在該Servlet實例,若存在,則直接讀取該實例響應請求;若是不存在,就建立一個Servlet實例。
(2) 初始化
實例化後,Servlet容器將調用Servlet的init()方法進行初始化(一些準備工做或資源預加載工做)。
(3)服務
初始化後,Servlet處於能響應請求的就緒狀態。當接收到客戶端請求時,調用service()的方法處理客戶端請求,HttpServlet的service()方法會根據不一樣的請求 轉調不一樣的doXxx()方法。
(4)銷燬
當Servlet容器關閉時,Servlet實例也隨時銷燬。其間,Servlet容器會調用Servlet 的destroy()方法去判斷該Servlet是否應當被釋放(或回收資源)。
9.farward和redirect區別
轉發(Forward),是一次請求,只有一個request,所以request域內的數據能夠共享。
重定向(Redirect)實際是兩次HTTP請求,服務器端在響應第一次請求的時候,讓瀏覽器再向另一個URL發出請求,從而達到轉發的目的。
10.final finally finalize區別
Java提供finalize()方法,垃圾回收器準備釋放內存的時候,會先調用finalize()。
11.樂觀鎖與悲觀鎖
悲觀鎖
老是假設最壞的狀況,每次去拿數據的時候都認爲別人會修改,因此每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻塞直到它拿到鎖 。傳統的關係型數據庫裏邊就用到了不少這種鎖機制,好比行鎖,表鎖等,讀鎖,寫鎖等,都是在作操做以前先上鎖。Java中synchronized 等獨佔鎖就是悲觀鎖思想的實現。
樂觀鎖
老是假設最好的狀況,每次去拿數據的時候都認爲別人不會修改,因此不會上鎖,可是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可使用版本號機制和CAS算法實現。樂觀鎖適用於多讀的應用類型,這樣能夠提升吞吐量,像數據庫提供的相似於write_condition機制,其實都是提供的樂觀鎖。在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實現方式CAS實現的。
兩種鎖的使用場景
衝突真的不多發生的時候,用樂觀鎖就比較合適。
常常產生衝突,用悲觀鎖就比較合適。
12.String、StringBuffer和StringBuilder的區別
在線程安全:StringBuilder是線程不安全的,而StringBuffer是線程安全的
運行速度:StringBuilder > StringBuffer > String
13.char能夠存儲漢字嗎爲何
char是按照字符存儲的,無論英文仍是中文 佔用佔用2個字節,用來儲存Unicode字符 unicode編碼字符集中包含了漢字,因此,char型變量中固然能夠存儲漢字啦。
15.簡述HashMap的實現原理
重寫HashMap須要重寫hashCode()和equals()方法
16.HashMap和HashTable的區別
線程不安全和線程不安全
鍵值可爲null鍵值不可爲null
前者快後者慢
咱們可否讓HashMap同步?
HashMap能夠經過下面的語句進行同步:
Map m = Collections.synchronizeMap(hashMap);
18.a=a+b與a+=b的區別
舉例:a爲int,b爲float 則a = a + b 須要強制類型轉換,也就是咱們常寫的 a = (int) (a+b);
而咱們的a += b 被咱們的編譯器在編譯期作了一些小手腳。也就是編譯器幫咱們進行了強制類型轉化。
& 和 &&的區別
&和&&均可以用做邏輯與的運算符
&&還具備短路的功能
&還能夠用做位運算符
深拷貝和淺拷貝的區別
打個不太恰當的比喻:一個是複製一份新的 一個是弄了一個快捷方式
Java的八大基本數據類型是什麼
byte short int long float double boolean char
進程、線程和協程的區別
1) 一個線程能夠多個協程,一個進程也能夠單獨擁有多個協程
2) 線程進程都是同步機制,而協程則是異步
3) 協程能保留上一次調用時的狀態,每次過程重入時,就至關於進入上一次調用的狀態
建立兩種線程的方式 他們有什麼區別
1.繼承Thread類
2.實現Runnable接口
守護線程:守護線程則是用來服務用戶線程的,若是沒有其餘用戶線程在運行,那麼就沒有可服務對象,守護線程就會退出。
Array(數組)和ArrayList(列表)有什麼區別
1)精闢闡述:
能夠將 ArrayList想象成一種「會自動擴增容量的Array」。
2)Array([]):數組,最高效;可是其容量固定且沒法動態改變;
ArrayList: 動態數組,容量可動態增加;但犧牲效率;
Runnable和Callable的區別
編寫多線程程序通常有三種方法,Thread,Runnable,Callable.
Runnable和Callable的區別是,
(1)Callable規定的方法是call(),Runnable規定的方法是run().
(2)Callable的任務執行後可返回值,而Runnable的任務是不能返回值得
(3)call方法能夠拋出異常,run方法不能夠
(4)Runnable是自從java1.1就有了,而Callable是1.5以後才加上去的
wait(),notify()和suspend(),resume()之間的區別
wait(),notify()有兩種形式一種是傳入一個時間參數,自動恢復,一種是不傳參,不會自動恢復,必須使用notify()方法
suspend(),resume():suspend()方法很容易引發死鎖問題,已經不推薦使用了。
default,public,private,protected區別
tomcat調優
聲明式事務
接口隔離
代碼塊、靜態代碼塊執行順序
Java子父類間靜態代碼塊、非靜態代碼塊、構造方法的執行順序
子類A繼承父類B,A a=new A();
正確的執行順序是:父類B靜態代碼塊->子類A靜態代碼塊->父類B非靜態代碼塊->父類B構造函數->子類A非靜態代碼塊->子類A構造函數
也就是說非靜態初始化塊的執行順序要在構造函數以前。
如何捕獲子線程異常線程設計的理念:「線程的問題應該線程本身自己來解決,而不要委託到外部。」