NO IMAGE

                              記阿里第一次面試

       好像是上個星期阿里給我打的電話,是的,電話面試,我是內推提交的簡歷。第一次是下午2點,第二次是下午4點,我都在睡覺,我覺得下午2點到4點是最好的睡覺時間,所以一般下午沒課,我都是2點到4點睡 午覺。第三次打電話大概是下午7點多了,這個時候長沙的天已經完全黑了。

      室友在吃雞,有點吵,於是我就跑到三樓到四樓的樓梯間去了。首先是自我介紹,這個就不說了,當時有點小緊張,沒有組織好語言,就簡單地把自己的學校、自己所學專業、老家哪的、在學校參加過什麼部門、做過哪些專案簡單地講了一下,但感覺確實沒有組織好語言。然後就是面試官的正式提問了,首先當然就是問專案的事了,要我簡單地把專案介紹一下,我就把專案從平臺性、有哪些功能、大概用了什麼技術和框架說了下,聽面試官司的語氣好像有點不滿意,確實,我做的那幾個專案已經有點久了,有點不記得了。我主要說了下用了Spring框架,面試官就問我SpringMVC的機制。我的回答是SpringMVC是基本DispatcherServlet的,也就是在Tomcat的架構下,配置的DispatcherServlet接收到Http請求,然後根據相關的路由,也就是一些HandlerMapping,通過這個HandlerMapping把請求對映到相應的Controller,然後就把請求引數封裝到相應的處理方法的引數中,然後就在Controller的方法裡執行業務邏輯,業務邏輯處理完後就返回一個ModelAndView物件,把這個物件交給檢視解析器,也就是ViewResolver解析,最後把結果返回給Servlet,給出Http請求的響應體。可能面試官對這個過程也不太瞭解,所以他也沒有繼續詢問細節了,還好沒問,其實我也就知道這麼多了。最近正在看《Spring技術內幕》這本書,還只看到了Ioc的實現那裡,後面的AOP和SpringMVC的實現細節還不是很瞭解。

     然後就問了用SpringMVC的好處,這個問題比較開放,我當時也懶得組織語言了,就簡單地把自己認為SpringMVC比較好的方面說了下,比如說可以解耦呀,比如可以和Spring無縫對接,讓Spring視窗管理物件,方便測試啥的。面試官對我的這個回答也好像不是很滿意,但我也沒辦法了,我就隨口說說的。

     然後再問了IoC和AOP的實現原理,我就回答IoC就是DI,用依賴注入管理物件之間的關係,比如說一個類中有另一個類的物件當屬性,那麼這兩個類就有了一定的關係,IoC就可以管理這種關係,通過配置的方式來讓一個物件注入到另一個物件中,而不是在一個物件中new另一個物件,如果直接new的話,就必須知道實現類是什麼,而物件導向程式設計提倡面向介面程式設計,也就是要儘量面向抽象,而不是面向實現,在一個類中的屬性或引數最好都用介面,而執行時才注入相應的實現類物件,Spring IoC就可以通過配置的方式來管理這些關係。這個就沒什麼好說的了。問我AOP是什麼,怎麼實現的,我就是AOP就是面向切面程式設計,也就是可以在一個方法執行前、執行後、或者丟擲異常時能夠做相應的處理,在應用中把這些有相同前置、後置或者異常處理的部分提取出來,統一管理就是切面了。實現方式就是設計模式中的代理模式,也就是要有一個呼叫物件的代理物件,在這個程式碼物件中持有被代理物件,當呼叫被代理物件的方法時,實際是呼叫的代理物件的相同方法,在這個方法中再呼叫被代理物件的方法,這時就可以在呼叫被代理方法之前、之後或者丟擲異常時做一些處理。這個回答他好像很滿意的樣子,他就再追問具體是怎樣實現的,我就說Spring有三種實現方式,分別是JDK自帶的動態代理、AspectJ框架,還有一種叫什麼名字來著的,他提醒我是cglib,我說“是是是,就是cglib”,場面一度很尷尬,我連這個居然都忘了,當時我臉都快紅了。然後他繼續追問我cglib的實現機制是什麼,我說是位元組碼技術,也就是動態生成了位元組碼,這種生成的位元組碼並不是儲存到class檔案中,而是直接存放在記憶體中,JVM通過類載入器去載入這些位元組碼資料,在記憶體中生成代理類的類資訊。這時他好像很高興的樣子,應該是對我居然還了解這麼低層的原理比較滿意吧。繼續問我對類載入機制了不瞭解,我說還比較瞭解。幸好寒假過年回家把《深入理解Java虛擬機器》這本書看了兩遍,對類載入過程有了大概的瞭解。我解釋道,類載入機制就是JVM把位元組碼解析成相應的類資訊儲存在記憶體中,這些位元組碼可能在class檔案中,也可能是一些網路資料,但不管怎麼說,都是一個位元組碼資料流,類載入器會把這個位元組碼流的資料載入到記憶體中,然後進行解析,把解析出的類資訊,比如說類有哪些屬性,有哪些方法什麼的,這些資訊儲存是方法區,然後生成一個Class物件,這個Class物件就是訪問這些類資訊的入口。然後他問我類載入有哪幾個階段,這時我有點方了,我記得《深入理解Java虛擬機器》裡確實是講過這個的,但我當時記不太清楚了,我說簡單地說了下,應該有載入過程、解析、初始化過程、使用過程和解除安裝過程吧,然後他幫我補充了驗證過程和準備過程,最終完整的過程應該是載入、驗證、準備、解析、初始化、使用、解除安裝。再此,不得不佩服阿里的技術大佬們,工作這麼久了,這些小知識點居然還記得這麼清楚,我想那些讀研的仁兄們應該從未聽說過java還有類載入機制吧,不過,術業有專攻嘛,讀研的同學們專心於學術和寫論文,這些在實際專案開發中的概念和理論瞭解得比較少也很正常。然後讓我簡單地描述一下類載入的過程,我就說把位元組碼資料先載入到記憶體,然後JVM就開始解析這些資料,把解析的類資訊儲存到方法區中,然後在初始化階段就初始化一些靜態變數和一些靜態程式碼塊的,在這個類載入的過程中用的一個什麼機制來著的,就是類載入器形成一個樹狀結構。他提醒我說是雙親委派模型,再問我為什麼叫雙親委派模型,我正準備說這個,就說java類載入器有四種,分別是Bootstrap ClassLoader,是載入jdk下的lib目錄中的jar檔案中的class類的,然後是擴充套件類載入器,是載入lib目錄下的一個擴充套件子目錄中的jar檔案中的class類的,然後是Application ClassLoader類載入器,是載入工作路徑中的類的,比如說在工程中自己寫的類或者新增的第三方jar包中的類。最後一種就是自定義的類載入器。這些類載入器是有父子關係的,比如說Bootstrap ClassLoader就沒有父載入器,而擴充套件類載入器的父載入器就是Bootstrap ClassLoader,應用類載入器的父載入器是擴充套件器載入器,然後自定義的類載入器的父載入器是應用類載入器,這樣就形成了一個樹狀結構。當一個類載入器在載入一個類時,會先用父載入器載入這個類,如果父類載入器也不能載入,就讓父類載入器的父類載入器載入,這樣一直到Bootstrap ClassLoader載入,就是先把載入任務委派給父類載入器載入,最後都載入不了後再自己試著載入,我說這就是我理解的為什麼叫雙親委派模型。他好像比較滿意,沒有糾錯,也沒有再深問下去。再此,應該要說一句,少年人,一定要多多看書呀,可以說,這次面試,我靠《深入理解Java虛擬機器》這本書就吹了半個多小時。

   然後他繼續問我對多執行緒和同步了不瞭解,我就回答,由於我學過兩年的Android程式設計,Android程式設計對執行緒要求比較高,所以我對多執行緒程式設計還算比較瞭解,然後他就說Andoroid中在非UI執行緒中更新UI會丟擲異常,問我會丟擲什麼異常,這個我就不清楚了,我也只知道如果直接在自己開的執行緒中操作UI的話,APP會直接崩掉的,我就說會丟擲不能在非UI執行緒中更新UI元件的異常,顯然他是不滿意的,但他肯定知道我也不知道是什麼異常,所以就放過我了。後來我上網查了一下,這個異常是CalledFromWrongThreadException。然後問我Android中線上程中更新UI有哪些方法,我就說常見的方法有四種,分別是使用Activity的runOnUIThread,在這個方法中傳入一個Runnable介面的物件,在Runnable的run方法中就可以更新UI。第二種是使用Handler類,線上程中構造一個Message物件,把要傳遞的引數新增到Message的引數中去,然後用Handler物件傳送這個Message訊息物件,這樣就可以在Handler的handleMessage方法中接收到這個Message訊息物件了,從這個訊息物件中取出相應的引數,根據這些引數就可以相應地更新UI了,然後第三種方法是用一個任務類,我當時沒有想起具體叫什麼名字了,就說好像叫AsycTask吧,裡面有個後臺執行方法,我們可以在這個後臺方法中執行相應的多執行緒操作,然後把執行的結果資料通過一個方法傳送出去,然後另外一個前臺方法就會被呼叫,引數就是我們在後臺執行中傳送的資料,通過這些資料,也可以相應地更新UI,第四種方法我當時沒有想出來,我說第四種方法我忘了。他也沒有提醒我,可能是他也不知道是什麼了吧。再此說一下,是View的post方法,傳入一個Runnable物件進去,根Activity的runOnUIThread方法一樣。接著他問我執行緒同步瞭解嗎,我說還比較瞭解,Java執行緒同步主要有兩種方法,一種就是傳統的用synchronous關鍵詞建立同步塊或者同步方法,用一個物件鎖把這個塊或者方法鎖住,持有相應鎖的執行緒只有一個執行緒能夠進入這個塊或方法,其他執行緒只能等待這個執行緒執行完後才能進入。第二種方法就是基於Lock介面的同步方法。感覺他應該是覺得我對Java基於掌握得還不錯,就不想在Java基本上再浪費時間了,就沒有再繼續問Java相關的了。

        再問我關於資料庫的,問我資料庫事務,我說是ACID,是原子性,一致性,隔離性,還有一種什麼來著,他提醒我說是永續性。哎,居然這都忘記了,我可是資料庫課考了90多分的男人,還不到一年就全忘了,在此,感覺好對不起講課讓人想睡覺的譚老師,老師還是講得蠻認真的,不過,他純粹地講課,真好太催眠了。然後問我資料庫查詢優化有哪些方法,我首先就想起了建立索引,然後他問我如果讓我來實現索引,應該用什麼資料結構,我說應該是用樹結構吧,他說mysql低層的資料結構就是用的樹,我說對對對,就是用的B 樹,然後他問我B 樹是什麼,我說我也不太瞭解,就是知道B 樹是一種特殊的樹,所有的葉節點都在最下面那一層,然後儲存的資料都在葉子節點中,非葉子節點只儲存了索引路徑。然後我就答不上來了,他應該也知道,就沒有再追問了。然後他說還有哪些方法可以優化sql嗎,我說應該還可以把比較具體的條件放到比較前面,這樣有得於索引,還有就是在聯表查詢時可以先查詢資料量比較小的,再鏈到比較大的表,現在才想到,這麼說完全是扯淡。他問我知不知道explain,我說不知道,然後他就跟我解釋explain可以檢視到sql語句執行的細節,比如說用到了哪些中間資料,哪些鍵,哪些引用或者索引,通過這些細節,就可以做相應的sql優化。我當時就懵了,我還真是第一次聽到sql中還有explain這個詞。只想說一句話,少年人,還是得多看書。

      然後他就沒再問我技術了,就問我一些關於考研的事、學習的事,最近在讀什麼書沒有,我就說在讀一本阿里的高階工程師寫的《大型網站系統與Java中介軟體實踐》的書,這本書裡講了網站如何從一個小網站演進成一個大網站,會遇到哪些常見的問題,並給出了一些解決方案,在這本書裡我收穫還是挺大的。然後我說還看了《深入理解Java虛擬機器》和《Java併發程式設計的藝術》,然後又講了一些雜七雜八的事。

     面了大概一個小時左右吧,最後他說我對基本掌握得比較好,讓我等待後面的面試通知。但我從他總體過程的語氣來看,他對我貌似並不怎麼滿意,感覺自己懸了。哎,掛了就掛了唄,自己確實沒有準備好,就寒假看了下《深入理解Java虛擬機器》和那個Java中介軟體的書,然後在同學都回家過年了自己一個人在寢室待了十幾天,看了些資料結構和演算法的東西,資料庫相關的東西完全沒複習,掛了就掛了吧,也不怨他人,第三次說那句話,少年人,還是得多看書。最後聽我們班其他面阿里的同學說,面他們的時候,整個過程完全是蒙的,問些基礎完全答不上來,非常尷尬。我又一想我,除了Java基礎還算拿得出手,其他東西,也就那樣,估計是涼了。哎。