致那些面試中的辛酸坎坷史.....
一、騰訊
面試時間:2019.12.18
面試部門:QQ 瀏覽器
你是如何來優化業務 RN 頁面的性能的?
在治理 RN 頁面的 JS 錯誤時,你的方案是什么,如何設計的方案?
MRN 比 原生 RN,有什么功能優勢?
MRN 頁面你們關注的性能指標有哪些?為什么要關注這些指標?
構造一個出現死鎖的情況
實現一個線程同步的計數器
synchronized 底層實現
說兩個線程同步的集合類
進程間通信的方式有哪些?
Activity 與 Service 的區別?Service 一定沒界面嗎,Activity 一定有界面嗎?
- Activity 不是一定有界面。比如一個跳轉邏輯控制類(機票的支付中間類)、透明頁
- Service 也不是一定沒界面。Service 并不依賴于用戶可視的 UI 界面,但這也不是絕對的,如前臺 Service 就是與 Notification 界面結合使用的;Service 中也可以彈 Toast;
- Service中執行 LayoutInflate 是合法的,但是會使用系統默認的主題樣式,如果你自定義了某些樣式可能不會被使用。所以從理論上看也是可以有界面的
- Activity 按 back 鍵退出,與強殺進程退出有啥區別?
(1)應用被強殺
- 整個App進程都被殺掉了,所有變量全都被清空,包括Application實例,更別提靜態變量;
- 雖然變量被清空了,但 Activity 棧沒有被清空,也就是說 A -> B -> C 這個棧還保存了,只是ABC 這幾個 Activity 實例沒有了。所以回到 App 時,顯示的還是 C 頁面。另外當 Activity 被強殺時,系統會調用 onSaveInstance 去讓你保存一些變量;
- 當應用回到前臺時,如果C頁面中有靜態變量或有些Application的全局變量,就NullPointer了;
- C頁面不會正常走完生命周期onStop & onDestory
(2)按 Back 鍵回退
- 應用進程不會被殺掉;Activity 棧由 A -> B -> C 變成 A -> B;
- C頁面會正常走完生命周期onStop & onDestory
構造一個內存泄露的場景
Android 虛擬機有哪些?區別是什么?
如何做屏幕適配,是否對小屏手機有專門的適配?
(1)Android 目前穩定高效的UI適配方案、今日頭條屏幕適配方案 AndroidAutoSize:
- dpi:屏幕像素密度,指的是在系統軟件上指定的單位尺寸的像素數量,它往往是寫在系統出廠配置文件的一個固定值;
- ppi:也是屏幕像素密度,但這個是物理上的概念,它是客觀存在的不會改變。dpi是軟件參考了物理像素密度后,人為指定的一個值,這樣保證了某一個區間內的物理像素密度在軟件上都使用同一個值
- dp加上自適應布局和weight比例布局能解決90%的適配問題。因為并不是所有的1080P的手機dpi都是480,比如Google 的Pixel2(1920*1080)的dpi是420
- 寬高限定符適配:窮舉市面上所有的Android手機的寬高像素值,設定一個基準的分辨率,其他分辨率都根據這個基準分辨率來計算,在不同的尺寸文件夾內部,根據該尺寸編寫對應的dimens文件。但其有一個致命的缺陷,那就是需要精準命中才能適配,App包體積也會變大
Java中中文字符和英文字符的大小分別多少?在網絡上傳輸大小又分別是多少?
Java GC機制,為什么要執行 GC
那些不可能再被任何途徑使用的對象,需要被回收,否則內存遲早都會被消耗空
平時開發中你是怎么保證質量的,團隊項目的質量又是如何保證的?
如何使用 git 來協作團隊開發流程的
項目 A 依賴 項目B,項目 B 依賴項目 C,項目C又依賴項目 A,這樣會有問題嗎?
上面的問題,給出有問題或沒問題的原因,怎么解決?
說一個你覺得讓你成長很大,或者印象比較深刻的項目
給你一個開發項目,如何管理,怎么制定開發規范
你覺得你相對其他的人的優勢是什么,劣勢是什么?
假設現在給你一個很有挑戰的難題去攻關,你會樂意去做嗎?
附:三個面過的騰訊算法題
- 求一個整數的二進制中 1 的個數
- 不知道頭結點的鏈表,刪除指定結點
- 字符串找首位最大重復子串
二、快手
面試時間:2019.12.19
面試部門:商業化
- hashcode 與 equal 區別?
(1)關系操作符 ==
- 若操作數的類型是基本數據類型,則該關系操作符判斷的是左右兩邊操作數的值是否相等
- 若操作數的類型是引用數據類型,則該關系操作符判斷的是左右兩邊操作數的內存地址是否相同。也就是說,若此時返回 true, 則該操作符作用的一定是同一個對象
(2)equals(內部實現三個步驟)
- 先 比較引用是否相同 (是否為同一對象)
- 再 判斷類型是否一致(是否為同一類型)
- 最后 比較內容是否一致
- 注:equal 的默認行為是比較引用,所以除非在自己的新類中覆蓋了 equal() 方法,否則不可能表現出我們希望的行為
(3)hashCode
- hashcode 是系統用來快速檢索對象而使用(一般在需要用哈希算法的數據結構中才有用,比如 HashSet, HashMap 和 Hashtable)
- 重寫 equals 方法和 hashcode 方法時,equals 方法中用到的成員變量也必定會在 hashcode 方法中用到,只不過前者作為比較項,后者作為生成摘要的信息項,本質上所用到的數據是一樣的,從而保證二者的一致性
(4)equals 與 hashCode 關系
- 如果兩個對象 equals,那么它們的 hashCode 必然相等
- 但是 hashCode 相等,equals 不一定相等
hashmap 實現原理,給一個 key 如何計算槽位,如何取值?
如何做的 RN 頁面的性能優化
Flutter 有了解過沒有?與 RN 的區別是什么
RN 與 Native 的對比
造成 oom 的原因
說一些引起內存泄漏的場景
內存泄漏怎么來檢測,LeakCanary 的原理是什么
檢測到內存泄漏怎么修復
service 的 bindservice() 與 startService 區別
requestLayout,invalidate 的區別
下面代碼是否能編譯通過:
Number[] a = new Integer[] {0}; // 能通過
List<Number> a = new ArrayList<Integer> (); // 不能通過
Serializable 與 Parcelable 的區別?
Serializable 中的 serialVersionUID 作用,如果修改了一個值,這個ID是否會改變?
Android Touch 事件的分發機制
橫向 ScrollView、縱向 ListView 怎么處理滑動手勢沖突
數據結構-二叉樹的廣度遍歷
其他若干項目相關問題
三、美團外賣
面試時間:2019.12.25
面試部門:外賣商家端
面試情況:已通過
- Java 虛擬機類加載器分類,類加載器的代理機制有什么好處?
(1)類加載器分類
- 啟動類加載器:加載 Java 的核心庫,是用原生代碼來實現的,并不繼承自 java.lang.ClassLoader;
- 擴展類加載器:加載 Java 的擴展庫。Java 虛擬機的實現會提供一個擴展庫目錄。該類加載器在此目錄里面查找并加載 Java 類;
- 系統/應用類加載器:它根據 Java 應用的類路徑(CLASSPATH)來加載 Java 類。一般來說,Java 應用的類都是由它來完成加載的。可以通過 ClassLoader.getSystemClassLoader()來獲取它;
- 注:類加載器樹狀組織結構,除了引導類加載器之外,所有的類加載器都有一個父類加載器。類加載器 Java 類如同其它的 Java 類一樣,也是要由類加載器來加載的。
(2)類加載器的代理機制
- 原理:類加載器在嘗試自己去查找某個類的字節代碼并定義它時,會先代理給其父類加載器,由父類加載器先去嘗試加載這個類,依次類推;
- 作用:代理模式是為了保證 Java 核心庫的類型安全。對于Java 核心庫的類的加載工作由引導類加載器來統一完成,保證了 Java 應用所使用的都是同一個版本的 Java 核心庫的類,是互相兼容的。
傳送門:深入探討 Java 類加載器
- Java 虛擬機是如何判定兩個 Java 類是相同的?
- Java 虛擬機不僅要看類的全名是否相同,還要看加載此類的類加載器 (defining loader) 是否一樣。即便是同樣的字節代碼,被不同的類加載器加載之后所得到的類,也是不同的;
- 不同的類加載器為相同名稱的類創建了額外的名稱空間。相同名稱的類可以并存在 Java 虛擬機中,只需要用不同的類加載器來加載它們即可。不同類加載器加載的類之間是不兼容的,這就相當于在 Java 虛擬機內部創建了一個個相互隔離的 Java 類空間。
- Java 類的加載過程是什么?
Java 類的加載過程 - 三個主要步驟:加載、鏈接、初始化:
(1)加載 - 將字節碼數據從不同的數據源讀取到 JVM 中,并映射為 JVM 認可的數據結構 (Class 對象)
- 由于類加載器的代理機制,啟動類加載過程的類加載器和真正完成類加載工作的類加載器,有可能不同;
- 啟動類的加載過程通過調用loadClass()來實現,稱為初始加載器 (initiating loader);而完成類的加載工作通過調用defineClass()來實現,稱為類的定義加載器 (defining loader)。在 Java 虛擬機判斷兩個類是否相同的時候,使用的是類的定義加載器;
- loadClass() 拋出的是 java.lang.ClassNotFoundException 異常,而 defineClass() 拋出的是 java.lang.NoClassDefFoundError 異常;
- 類加載器在成功加載某個類之后,會把得到的 java.lang.Class 類的實例緩存起來。下次再請求加載該類的時候,類加載器會直接使用緩存的類的實例,而不會嘗試再次加載 (即 loadClass()不會被重復調用)
(2)鏈接 - 將原始的類定義信息平滑地轉化入 JVM 運行的過程中
- 驗證:核驗字節信息是符合 Java 虛擬機規范;
- 準備:創建類或接口中的靜態變量并初始化,側重分配所需要的內存空間(與初始化階段區分開);
- 解析:替換常量池中的符號引用為直接引用,類、接口、方法和字段等各個方面的解析等
(3)初始化 - 真正執行類初始化的代碼邏輯,包括靜態字段賦值的動作,以及類中靜態初始化塊內的邏輯。編譯器在編譯階段就會把這部分邏輯整理好,父類型的初始化邏輯優先于當前類型的邏輯
Java 中的幾種引用類型,虛引用的使用場景?
Java GC 的幾種算法
Java GC 是如何判斷對象是可以被回收的?
- 自動垃圾收集的前提是清楚哪些內存可以被釋放,主要有兩個方面,最主要部分就是對象實例,存儲在堆上的;另一個是方法區中的元數據等信息,例如類型不再使用,卸載該 Java 類比較合理;
- 對象實例收集主要是兩種基本算法,引用計數和可達性分析,Java 選擇的可達性分析。JVM 會把虛擬機棧和本地方法棧中正在引用的對象、靜態屬性引用的對象和常量**,作為 GC Roots。
- synchronized 的 4 種狀態
- 不可不說的Java“鎖”事
- 訪問 synchronized 修飾static方法、synchronized(this|object) 是否會沖突受干擾
- 訪問 synchronized 修飾 static 方法、synchronized (類.class) 是否會沖突受干擾
- okhttp 在 response 返回后,調用了 response.toString(),后面再使用 response 會用什么問題?
調用 response.toString() 連接會斷開,后面的取值會出問題!魔性的問題...
Handler 空閑會不會阻塞主線程,IdleHandler 使用場景
LeakCanary 的收集內存泄露是在 Activity 的什么時機,大致原理
如何修復匿名內部類 handler 造成的內存泄露?
Handler 機制中是怎么保證每個線程的 Looper 是唯一的?
泛型擦除發生的時機是什么時候?
在編譯期。我眼中的Java-Type體系
MRN 單工程多 bundle,單工程單 bundle 的優缺點對比
MRN 長列表的性能問題,頁面白屏
介紹下 Redux 的工作原理
創建線程池的幾個關鍵參數(核心線程、最大線程....)
Retrofit 的實現原理,使用了什么的設計模式?優勢是什么?
Gradle 的工作原理
RN中,JS 與 Native 是怎么通信的?
MRN 的初始化過程?如何加載 NativeModule 的?
MRN 的頁面(也就是bundle)緩存機制
對于 MRN,你們是怎么處理 JNI 異常的?
其他項目相關問題
文中若有不對的地方,歡迎大家批評斧正,謝謝~