1. 程式人生 > 其它 >Android自學!15個經典面試問題及回答思路,終局之戰

Android自學!15個經典面試問題及回答思路,終局之戰

前言

從去年底到前幾天,不斷被各路跳槽的朋友刺激著,他們都跟我說著同一件事:跳槽了,薪資翻倍了,去一家叫做位元組跳動的公司了。

讓我更加訝異的是一個在微博做移動開發的朋友跟我說他捨棄了年終獎,在春節之前就投入到這家公司的懷抱,這讓我一度以為這個朋友是被傳銷了。

說實話,我內心早就被這些個朋友成功跳槽的訊息撩撥的春心蕩漾了,在這春色融融的夜晚我的程式碼也開始位元組跳動了,今晚就跟大家分享下這些朋友們跳槽的故事。

1、java中==和equals和hashCode的區別
基本資料型別的比較的值相等.
類的
比較的記憶體的地址,即是否是同一個物件,在不覆蓋equals的情況下,同比較記憶體地址,原實現也為 == ,如String等重寫了equals方法.
hashCode也是Object類的一個方法。返回一個離散的int型整數。在集合類操作中使用,為了提高查詢速度。(HashMap,HashSet等比較是否為同一個)
如果兩個物件equals,Java執行時環境會認為他們的hashcode一定相等。
如果兩個物件不equals,他們的hashcode有可能相等。
如果兩個物件hashcode相等,他們不一定equals。
如果兩個物件hashcode不相等,他們一定不equals。

2、int與integer的區別
int 基本型別
integer 物件 int的封裝類

3、String、StringBuffer、StringBuilder區別
String:字串常量 不適用於經常要改變值得情況,每次改變相當於生成一個新的物件
StringBuffer:字串變數 (執行緒安全)
StringBuilder:字串變數(執行緒不安全) 確保單執行緒下可用,效率略高於StringBuffer

4、什麼是內部類?內部類的作用
內部類可直接訪問外部類的屬性
Java中內部類主要分為成員內部類、區域性內部類(巢狀在方法和作用域內)、匿名內部類(沒構造方法)、靜態內部類(static修飾的類,不能使用任何外圍類的非static成員變數和方法, 不依賴外圍類)

5、程序和執行緒的區別
程序是cpu資源分配的最小單位,執行緒是cpu排程的最小單位。
程序之間不能共享資源,而執行緒共享所在程序的地址空間和其它資源。
一個程序內可擁有多個執行緒,程序可開啟程序,也可開啟執行緒。
一個執行緒只能屬於一個程序,執行緒可直接使用同進程的資源,執行緒依賴於程序而存在。

6、final,finally,finalize的區別
final:修飾類、成員變數和成員方法,類不可被繼承,成員變數不可變,成員方法不可重寫
finally:與try...catch...共同使用,確保無論是否出現異常都能被呼叫到
finalize:類的方法,垃圾回收之前會呼叫此方法,子類可以重寫finalize()方法實現對資源的回收

7、Serializable 和Parcelable 的區別
Serializable Java 序列化介面 在硬碟上讀寫 讀寫過程中有大量臨時變數的生成,內部執行大量的i/o操作,效率很低。
Parcelable Android 序列化介面 效率高 使用麻煩 在記憶體中讀寫(AS有相關外掛 一鍵生成所需方法) ,物件不能儲存到磁碟中

8、靜態屬性和靜態方法是否可以被繼承?是否可以被重寫?以及原因?
可繼承 不可重寫 而是被隱藏
如果子類裡面定義了靜態方法和屬性,那麼這時候父類的靜態方法或屬性稱之為"隱藏"。如果你想要呼叫父類的靜態方法和屬性,直接通過父類名.方法或變數名完成。

9、成員內部類、靜態內部類、區域性內部類和匿名內部類的理解,以及專案中的應用
java中內部類主要分為成員內部類、區域性內部類(巢狀在方法和作用域內)、匿名內部類(沒構造方法)、靜態內部類(static修飾的類,不能使用任何外圍類的非static成員變數和方法, 不依賴外圍類)
使用內部類最吸引人的原因是:每個內部類都能獨立地繼承一個(介面的)實現,所以無論外圍類是否已經繼承了某個(介面的)實現,對於內部類都沒有影響。
因為Java不支援多繼承,支援實現多個介面。但有時候會存在一些使用介面很難解決的問題,這個時候我們可以利用內部類提供的、可以繼承多個具體的或者抽象的類的能力來解決這些程式設計問題。可以這樣說,介面只是解決了部分問題,而內部類使得多重繼承的解決方案變得更加完整。

10、string 轉換成 integer的方式及原理
String ?integer Intrger.parseInt(string);
Integer?string Integer.toString();
11、哪些情況下的物件會被垃圾回收機制處理掉?
1.所有例項都沒有活動執行緒訪問。
2.沒有被其他任何例項訪問的迴圈引用例項。
3.Java 中有不同的引用型別。判斷例項是否符合垃圾收集的條件都依賴於它的引用型別。
要判斷怎樣的物件是沒用的物件。這裡有2種方法:
1.採用標記計數的方法:
給記憶體中的物件給打上標記,物件被引用一次,計數就加1,引用被釋放了,計數就減一,當這個計數為0的時候,這個物件就可以被回收了。當然,這也就引發了一個問題:迴圈引用的物件是無法被識別出來並且被回收的。所以就有了第二種方法:
2.採用根搜尋演算法:
從一個根出發,搜尋所有的可達物件,這樣剩下的那些物件就是需要被回收的

12、靜態代理和動態代理的區別,什麼場景使用?
靜態代理類:
由程式設計師建立或由特定工具自動生成原始碼,再對其編譯。在程式執行前,代理類的.class檔案就已經存在了。動態代理類:在程式執行時,運用反射機制動態建立而成。

14、Java中實現多型的機制是什麼?
答:方法的重寫Overriding和過載Overloading是Java多型性的不同表現
重寫Overriding是父類與子類之間多型性的一種表現
過載Overloading是一個類中多型性的一種表現.

16、說說你對Java反射的理解
JAVA反射機制是在執行狀態中, 對於任意一個類, 都能夠知道這個類的所有屬性和方法; 對於任意一個物件, 都能夠呼叫它的任意一個方法和屬性。 從物件出發,通過反射(Class類)可以取得取得類的完整資訊(類名 Class型別,所在包、具有的所有方法 Method[]型別、某個方法的完整資訊(包括修飾符、返回值型別、異常、引數型別)、所有屬性 Field[]、某個屬性的完整資訊、構造器 Constructors),呼叫類的屬性或方法自己的總結: 在執行過程中獲得類、物件、方法的所有資訊。

17、說說你對Java註解的理解
元註解
元註解的作用就是負責註解其他註解。java5.0的時候,定義了4個標準的meta-annotation型別,它們用來提供對其他註解的型別作說明。

1.@Target
2.@Retention
3.@Documented
4.@Inherited
18、Java中String的瞭解
在原始碼中string是用final 進行修飾,它是不可更改,不可繼承的常量。

19、String為什麼要設計成不可變的?
1、字串池的需求
字串池是方法區(Method Area)中的一塊特殊的儲存區域。當一個字串已經被建立並且該字串在 池 中,該字串的引用會立即返回給變數,而不是重新建立一個字串再將引用返回給變數。如果字串不是不可變的,那麼改變一個引用(如: string2)的字串將會導致另一個引用(如: string1)出現髒資料。
2、允許字串快取雜湊碼
在java中常常會用到字串的雜湊碼,例如: HashMap 。String的不變性保證雜湊碼始終一,因此,他可以不用擔心變化的出現。 這種方法意味著不必每次使用時都重新計算一次雜湊碼——這樣,效率會高很多。
3、安全
String廣泛的用於java 類中的引數,如:網路連線(Network connetion),開啟檔案(opening files )等等。如果String不是不可變的,網路連線、檔案將會被改變——這將會導致一系列的安全威脅。操作的方法本以為連線上了一臺機器,但實際上卻不是。由於反射中的引數都是字串,同樣,也會引起一系列的安全問題。

20、Object類的equal和hashCode方法重寫,為什麼?
首先equals與hashcode間的關係是這樣的:
1、如果兩個物件相同(即用equals比較返回true),那麼它們的hashCode值一定要相同;
2、如果兩個物件的hashCode相同,它們並不一定相同(即用equals比較返回false)
由於為了提高程式的效率才實現了hashcode方法,先進行hashcode的比較,如果不同,那沒就不必在進行equals的比較了,這樣就大大減少了equals比較的次數,這對比需要比較的數量很大的效率提高是很明顯的

21、List,Set,Map的區別
Set是最簡單的一種集合。集合中的物件不按特定的方式排序,並且沒有重複物件。 Set介面主要實現了兩個實現類:HashSet: HashSet類按照雜湊演算法來存取集合中的物件,存取速度比較快
TreeSet :TreeSet類實現了SortedSet介面,能夠對集合中的物件進行排序。
List的特徵是其元素以線性方式儲存,集合中可以存放重複物件。
ArrayList() : 代表長度可以改變得陣列。可以對元素進行隨機的訪問,向ArrayList()中插入與刪除元素的速度慢。
LinkedList(): 在實現中採用連結串列資料結構。插入和刪除速度快,訪問速度慢。
Map 是一種把鍵物件和值物件對映的集合,它的每一個元素都包含一對鍵物件和值物件。 Map沒有繼承於Collection介面 從Map集合中檢索元素時,只要給出鍵物件,就會返回對應的值物件。
HashMap:Map基於散列表的實現。插入和查詢“鍵值對”的開銷是固定的。可以通過構造器設定容量capacity和負載因子load factor,以調整容器的效能。
LinkedHashMap: 類似於HashMap,但是迭代遍歷它時,取得“鍵值對”的順序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一點。而在迭代訪問時發而更快,因為它使用連結串列維護內部次序。
TreeMap : 基於紅黑樹資料結構的實現。檢視“鍵”或“鍵值對”時,它們會被排序(次序由Comparabel或Comparator決定)。TreeMap的特點在 於,你得到的結果是經過排序的。TreeMap是唯一的帶有subMap()方法的Map,它可以返回一個子樹。
WeakHashMao :弱鍵(weak key)Map,Map中使用的物件也被允許釋放: 這是為解決特殊問題設計的。如果沒有map之外的引用指向某個“鍵”,則此“鍵”可以被垃圾收集器回收。

26、ArrayMap和HashMap的對比
1、儲存方式不同
HashMap內部有一個HashMapEntry<K, V>[]物件,每一個鍵值對都儲存在這個物件裡,當使用put方法新增鍵值對時,就會new一個HashMapEntry物件,
2、新增資料時擴容時的處理不一樣,進行了new操作,重新建立物件,開銷很大。ArrayMap用的是copy資料,所以效率相對要高。
3、ArrayMap提供了陣列收縮的功能,在clear或remove後,會重新收縮陣列,是否空間
4、ArrayMap採用二分法查詢;

29、HashMap和HashTable的區別
1 HashMap不是執行緒安全的,效率高一點、方法不是Synchronize的要提供外同步,有containsvalue和containsKey方法。
hashtable是,執行緒安全,不允許有null的鍵和值,效率稍低,方法是是Synchronize的。有contains方法方法。Hashtable 繼承於Dictionary 類

30、HashMap與HashSet的區別
hashMap:HashMap實現了Map介面,HashMap儲存鍵值對,使用put()方法將元素放入map中,HashMap中使用鍵物件來計算hashcode值,HashMap比較快,因為是使用唯一的鍵來獲取物件。
HashSet實現了Set介面,HashSet僅僅儲存物件,使用add()方法將元素放入set中,HashSet使用成員物件來計算hashcode值,對於兩個物件來說hashcode可能相同,所以equals()方法用來判斷物件的相等性,如果兩個物件不同的話,那麼返回false。HashSet較HashMap來說比較慢。

31、HashSet與HashMap怎麼判斷集合元素重複?
HashSet不能新增重複的元素,當呼叫add(Object)方法時候,
首先會呼叫Object的hashCode方法判hashCode是否已經存在,如不存在則直接插入元素;如果已存在則呼叫Object物件的equals方法判斷是否返回true,如果為true則說明元素已經存在,如為false則插入元素。

33、ArrayList和LinkedList的區別,以及應用場景
ArrayList是基於陣列實現的,ArrayList執行緒不安全。
LinkedList是基於雙鏈表實現的:
使用場景:
(1)如果應用程式對各個索引位置的元素進行大量的存取或刪除操作,ArrayList物件要遠優於LinkedList物件;
( 2 ) 如果應用程式主要是對列表進行迴圈,並且迴圈時候進行插入或者刪除操作,LinkedList物件要遠優於ArrayList物件;

34、陣列和連結串列的區別
陣列:是將元素在記憶體中連續儲存的;它的優點:因為資料是連續儲存的,記憶體地址連續,所以在查詢資料的時候效率比較高;它的缺點:在儲存之前,我們需要申請一塊連續的記憶體空間,並且在編譯的時候就必須確定好它的空間的大小。在執行的時候空間的大小是無法隨著你的需要進行增加和減少而改變的,當資料兩比較大的時候,有可能會出現越界的情況,資料比較小的時候,又有可能會浪費掉記憶體空間。在改變資料個數時,增加、插入、刪除資料效率比較低。
連結串列:是動態申請記憶體空間,不需要像陣列需要提前申請好記憶體的大小,連結串列只需在用的時候申請就可以,根據需要來動態申請或者刪除記憶體空間,對於資料增加和刪除以及插入比陣列靈活。還有就是連結串列中資料在記憶體中可以在任意的位置,通過應用來關聯資料(就是通過存在元素的指標來聯絡)

35、開啟執行緒的三種方式?
ava有三種建立執行緒的方式,分別是繼承Thread類、實現Runable介面和使用執行緒池

36、執行緒和程序的區別?
執行緒是程序的子集,一個程序可以有很多執行緒,每條執行緒並行執行不同的任務。不同的程序使用不同的記憶體空間,而所有的執行緒共享一片相同的記憶體空間。別把它和棧記憶體搞混,每個執行緒都擁有單獨的棧記憶體用來儲存本地資料。

38、run()和start()方法區別
這個問題經常被問到,但還是能從此區分出面試者對Java執行緒模型的理解程度。start()方法被用來啟動新建立的執行緒,而且start()內部呼叫了run()方法,這和直接呼叫run()方法的效果不一樣。當你呼叫run()方法的時候,只會是在原來的執行緒中呼叫,沒有新的執行緒啟動,start()方法才會啟動新執行緒。

39、如何控制某個方法允許併發訪問執行緒的個數?
semaphore.acquire() 請求一個訊號量,這時候的訊號量個數-1(一旦沒有可使用的訊號量,也即訊號量個數變為負數時,再次請求的時候就會阻塞,直到其他執行緒釋放了訊號量)
semaphore.release() 釋放一個訊號量,此時訊號量個數+1

40、在Java中wait和seelp方法的不同;
Java程式中wait 和 sleep都會造成某種形式的暫停,它們可以滿足不同的需要。wait()方法用於執行緒間通訊,如果等待條件為真且其它執行緒被喚醒時它會釋放鎖,而sleep()方法僅僅釋放CPU資源或者讓當前執行緒停止執行一段時間,但不會釋放鎖。

41、談談wait/notify關鍵字的理解
等待物件的同步鎖,需要獲得該物件的同步鎖才可以呼叫這個方法,否則編譯可以通過,但執行時會收到一個異常:IllegalMonitorStateException。
呼叫任意物件的 wait() 方法導致該執行緒阻塞,該執行緒不可繼續執行,並且該物件上的鎖被釋放。
喚醒在等待該物件同步鎖的執行緒(只喚醒一個,如果有多個在等待),注意的是在呼叫此方法的時候,並不能確切的喚醒某一個等待狀態的執行緒,而是由JVM確定喚醒哪個執行緒,而且不是按優先順序。
呼叫任意物件的notify()方法則導致因呼叫該物件的 wait()方法而阻塞的執行緒中隨機選擇的一個解除阻塞(但要等到獲得鎖後才真正可執行)。

42、什麼導致執行緒阻塞?執行緒如何關閉?
阻塞式方法是指程式會一直等待該方法完成期間不做其他事情,ServerSocket的accept()方法就是一直等待客戶端連線。這裡的阻塞是指呼叫結果返回之前,當前執行緒會被掛起,直到得到結果之後才會返回。此外,還有非同步和非阻塞式方法在任務完成前就返回。
一種是呼叫它裡面的stop()方法
另一種就是你自己設定一個停止執行緒的標記 (推薦這種)

43、如何保證執行緒安全?
1.synchronized;
2.Object方法中的wait,notify;
3.ThreadLocal機制 來實現的。

44、如何實現執行緒同步?
1、synchronized關鍵字修改的方法。2、synchronized關鍵字修飾的語句塊3、使用特殊域變數(volatile)實現執行緒同步

45、執行緒間操作List
List list = Collections.synchronizedList(new ArrayList());

46、談談對Synchronized關鍵字,類鎖,方法鎖,重入鎖的理解
java的物件鎖和類鎖:java的物件鎖和類鎖在鎖的概念上基本上和內建鎖是一致的,但是,兩個鎖實際是有很大的區別的,物件鎖是用於物件例項方法,或者一個物件例項上的,類鎖是用於類的靜態方法或者一個類的class物件上的。我們知道,類的物件例項可以有很多個,但是每個類只有一個class物件,所以不同物件例項的物件鎖是互不干擾的,但是每個類只有一個類鎖。但是有一點必須注意的是,其實類鎖只是一個概念上的東西,並不是真實存在的,它只是用來幫助我們理解鎖定例項方法和靜態方法的區別的

49、synchronized 和volatile 關鍵字的區別
1.volatile本質是在告訴jvm當前變數在暫存器(工作記憶體)中的值是不確定的,需要從主存中讀取;synchronized則是鎖定當前變數,只有當前執行緒可以訪問該變數,其他執行緒被阻塞住。
2.volatile僅能使用在變數級別;synchronized則可以使用在變數、方法、和類級別的
3.volatile僅能實現變數的修改可見性,不能保證原子性;而synchronized則可以保證變數的修改可見性和原子性
4.volatile不會造成執行緒的阻塞;synchronized可能會造成執行緒的阻塞。
5.volatile標記的變數不會被編譯器優化;synchronized標記的變數可以被編譯器優化
51、ReentrantLock 、synchronized和volatile比較
ava在過去很長一段時間只能通過synchronized關鍵字來實現互斥,它有一些缺點。比如你不能擴充套件鎖之外的方法或者塊邊界,嘗試獲取鎖時不能中途取消等。Java 5 通過Lock介面提供了更復雜的控制來解決這些問題。 ReentrantLock 類實現了 Lock,它擁有與 synchronized 相同的併發性和記憶體語義且它還具有可擴充套件性。

53、死鎖的四個必要條件?
死鎖產生的原因

系統資源的競爭
系統資源的競爭導致系統資源不足,以及資源分配不當,導致死鎖。
程序執行推進順序不合適
互斥條件:一個資源每次只能被一個程序使用,即在一段時間內某 資源僅為一個程序所佔有。此時若有其他程序請求該資源,則請求程序只能等待。
請求與保持條件:程序已經保持了至少一個資源,但又提出了新的資源請求,而該資源 已被其他程序佔有,此時請求程序被阻塞,但對自己已獲得的資源保持不放。
不可剝奪條件:程序所獲得的資源在未使用完畢之前,不能被其他程序強行奪走,即只能 由獲得該資源的程序自己來釋放(只能是主動釋放)。
迴圈等待條件: 若干程序間形成首尾相接迴圈等待資源的關係
這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。
死鎖的避免與預防:
死鎖避免的基本思想:
系統對程序發出每一個系統能夠滿足的資源申請進行動態檢查,並根據檢查結果決定是否分配資源,如果分配後系統可能發生死鎖,則不予分配,否則予以分配。這是一種保證系統不進入死鎖狀態的動態策略。
理解了死鎖的原因,尤其是產生死鎖的四個必要條件,就可以最大可能地避免、預防和解除死鎖。所以,在系統設計、程序排程等方面注意如何讓這四個必要條件不成立,如何確定資源的合理分配演算法,避免程序永久佔據系統資源。此外,也要防止程序在處於等待狀態的情況下佔用資源。因此,對資源的分配要給予合理的規劃。
死鎖避免和死鎖預防的區別:
死鎖預防是設法至少破壞產生死鎖的四個必要條件之一,嚴格的防止死鎖的出現,而死鎖避免則不那麼嚴格的限制產生死鎖的必要條件的存在,因為即使死鎖的必要條件存在,也不一定發生死鎖。死鎖避免是在系統執行過程中注意避免死鎖的最終發生。
56、什麼是執行緒池,如何使用?
建立執行緒要花費昂貴的資源和時間,如果任務來了才建立執行緒那麼響應時間會變長,而且一個程序能建立的執行緒數有限。為了避免這些問題,在程式啟動的時候就建立若干執行緒來響應處理,它們被稱為執行緒池,裡面的執行緒叫工作執行緒。從JDK1.5開始,Java API提供了Executor框架讓你可以建立不同的執行緒池。比如單執行緒池,每次處理一個任務;數目固定的執行緒池或者是快取執行緒池(一個適合很多生存期短的任務的程式的可擴充套件執行緒池)。

57、Java中堆和棧有什麼不同?
為什麼把這個問題歸類在多執行緒和併發面試題裡?因為棧是一塊和執行緒緊密相關的記憶體區域。每個執行緒都有自己的棧記憶體,用於儲存本地變數,方法引數和棧呼叫,一個執行緒中儲存的變數對其它執行緒是不可見的。而堆是所有執行緒共享的一片公用記憶體區域。物件都在堆裡建立,為了提升效率執行緒會從堆中弄一個快取到自己的棧,如果多個執行緒使用該變數就可能引發問題,這時volatile 變數就可以發揮作用了,它要求執行緒從主存中讀取變數的值。

58、有三個執行緒T1,T2,T3,怎麼確保它們按順序執行?
在多執行緒中有多種方法讓執行緒按特定順序執行,你可以用執行緒類的join()方法在一個執行緒中啟動另一個執行緒,另外一個執行緒完成該執行緒繼續執行。為了確保三個執行緒的順序你應該先啟動最後一個(T3呼叫T2,T2呼叫T1),這樣T1就會先完成而T3最後完成。
執行緒間通訊
我們知道執行緒是CPU排程的最小單位。在Android中主執行緒是不能夠做耗時操作的,子執行緒是不能夠更新UI的。而執行緒間通訊的方式有很多,比如廣播,Eventbus,介面回掉,在Android中主要是使用handler。handler通過呼叫sendmessage方法,將儲存訊息的Message傳送到Messagequeue中,而looper物件不斷的呼叫loop方法,從messageueue中取出message,交給handler處理,從而完成執行緒間通訊。

題外話

不管怎麼樣,不論是什麼樣的大小面試,要想不被面試官虐的不要不要的,只有刷爆面試題題做好全面的準備,當然除了這個還需要在平時把自己的基礎打紮實,這樣不論面試官怎麼樣一個知識點裡往死裡鑿,你也能應付如流啊~

這裡我為大家準備了一些我工作以來以及參與過的大大小小的面試收集總結出來的一套進階學習的視訊及面試專題資料包,點選這裡免費分享給大家,主要還是希望大家在如今大環境不好的情況下面試能夠順利一點,希望可以幫助到大家~

最後如果馬化騰把騰訊給你一天,你會來做什麼?歡迎評論區討論。