1. 程式人生 > >Java面試題【暫停更新中,待博主有時間再更新】

Java面試題【暫停更新中,待博主有時間再更新】

大學四年也即將要結束了,都說畢業即“失業”,但是不能就這樣從命吧。所以自己也在努力的找工作中,寫一篇JAVA的面試題,可能當中寫的不好,或者出現錯誤,見諒。話不多說,直接開始正題。(敲黑板)

Java中堆(heap)和棧(stack)的區別?

  1. 棧的存取速度比較快,僅次於位於CPU的暫存器,缺點是棧中資料大小和生存期必須是確定的,缺乏靈活性。另外,棧的資料是共享的(詳見b),而棧的優勢是可以動態的分配記憶體且生存期可以不用告訴編譯器,缺點是因為在執行時動態的分配記憶體,所以存取速度會較慢
  2. 定義: int a = 3; int b = 3;編譯器先在棧中建立一個變數為3的引用。然後查詢棧中是否存有3這個數值的地址,如果沒有,則開闢一個記憶體來存放,接著將a引用指向3的地址。接著建立變數b,這個時候棧中已經存在有3這個數值的地址,直接將b指向3。這個就是棧的資料共享。

【該種字面值的引用與類物件的引用不同,就是假如接著將a改為4後,b並不會指向4,而類物件引用的情況則是:當兩個類物件同時引用一個物件時,其中一個物件改變了引用物件的內部狀態,則另一個物件的引用也立馬發生改變】

什麼是JAVA反射機制?

概念:在執行狀態中,對於任意類,都能夠獲取到其屬性和方法,對於任意物件,都能夠呼叫其屬性和方法。這種在執行時動態獲取資訊以及動態呼叫物件方法的功能叫JAVA的反射機制。

JAVA獲取位元組碼物件有幾種方式?

三種:分別是:靜態屬性.class、Object類中的getClaa()方法、Class.forName(“類的全路徑”)【重點,最常用】

靜態屬性.classàStudeng studet = new Student();  student.class;

Object類中的getClaa()方法à Studeng studet = new Student();  student.getClass();

Class.forName()方式àStudeng studet = Class.forName(“com.cuc.service.student”); 

POST和GET的區別?

  1. 安全性:GET方式會將資訊顯示在URL中,地址和引數用?連線,引數與引數之間用&連線;而POST請求是將資料放在Http的body中,位址列不可見
  2. 大小限制:根據瀏覽器的不同,對URL的長度有進行限制,最大長度為2k(2048)
  3. 歷史上:伺服器的增/刪/改/查方法分別是put/delete/post/get
  4. 速度上:GET的速度會比POST的更快
  5. 傳送方式:GET是將請求頭http head和資料data一併傳送出去,伺服器響應200(返回資料),POST是先將請求頭http head傳送,伺服器響應100(continu,再發送資料data,伺服器響應200(返回資料)

Interface和abstract類的區別?

   Inteface(介面):

  1. 包含有常量(不是變數)和抽象方法
  2. 常量都是public,final,static(可以省略不寫)
  3. 抽象方法的許可權都是public(允許省略public,static)
  4. 介面可以被繼承,一個介面可以通過extends來繼承另一個介面

   Abstract類(抽象類):

  1. 抽象類中可以沒有抽象方法,抽象方法必須在抽象類中
  2. 抽象類不能進行例項化,及不能使用new關鍵字來建立物件
  3. 抽象方法,只能宣告,不能新增final和static關鍵字進行修飾

什麼是AOP(面向切面程式設計)?

擴充套件功能時,不修改原始碼,將功能程式碼從業務邏輯程式碼中分離出來。傳統的面向物件程式設計是採用縱向繼承體系重複性程式碼

AOP底層的實現原理(2種):JDK動態代理,該方式要求物件是實現了介面的類;cglib動態代理則是針對類,沒有要求實現介面。

Final,finally,finalize()的區別?

  1. Final關鍵字:用於修飾變數為常量,常量一般為大寫且需要進行初始化,之後不能被修改,用於修飾方法時,表明該方法不能被重寫,為最終方法的意思,在修飾類的時候,表示該類不能夠被繼承。
  2. Finally:主要用於異常上,和try…catch一起使用,主要用於關閉連線或清除之類的操作。
  3. Finalize():該方法主要是在垃圾回收機制(GC)之前進行呼叫。

Throws,throw和try{}catch{}的區別?

  1. Throws:用於方法名稱後,表示該方法可能丟擲某種異常。
  2. Throw:用於程式碼塊中,當代碼執行到這裡時,一定丟擲某種異常。
  3. Try{}catch{}:當try裡面的程式碼塊出現異常時,會被捕捉到並進入catch中,執行catch裡面的程式碼塊。

B/S和C/S的區別?

  1. B/S:即Browser/Service(瀏覽器/伺服器),使用者通過瀏覽器網頁的形式進行訪問,使用者只需要有瀏覽器即可,新增新功能時,不需要使用者更新,更注重於服務端
  2. C/S:即Client/Service(客戶端/伺服器),需要使用者下載客戶端(例如APP),當有新功能增加時,需要使用者進行更新,需注重於客戶端和服務的兩方面

List和set和Map?

  1. List可以允許重複物件,而set不允許重複物件,前面兩者都是collection的子介面或實現類,Map是一個介面
  2. List可以插入多個null元素,set只允許最多包含一個null元素,Map允許有隨意個null值,但是隻允許擁有一個null鍵
  3. List是有序的,set是無序的,Map的是鍵值對的形式,允許有相同的值,但是鍵只能是唯一的。
  4. List常用的實現類有ArrayList,LinkedList和Vector。Set常用的實現類有Hashset,LinkedHashSet和ThreeSet。Map常用的實現類有HashMap,LinkedHashMap,Hashtable和ThreeMap

List和Set和Map的應用場景?

  1. 使用索引訪問資料時,採用List,ArrayList可以更快的訪問,如果經常是新增/刪除資料的話,採用LinkedList。
  2. 如果想要值不重複的話,採用set,可以保證插入的元素是唯一的。
  3. 如果想要是有序的儲存的,則選擇List,如果想要無序的儲存,則選擇set。
  4. 如果是已鍵值對的形式儲存資料,則選擇Map。

轉發(forward)和重定向(redirect)的區別?

  1. 從url來看:轉發是由伺服器進行請求資源,瀏覽器傳送轉發請求,伺服器直接訪問目標地址的URL來獲取資源,然後返回給瀏覽器,瀏覽器並不知道資源來自哪裡,所以位址列並沒有變化。而重定向,瀏覽器傳送重定向請求到伺服器,伺服器返回一個狀態碼(例如301,302),瀏覽器收到狀態碼後重新去請求獲取資源。
  2. 從資料共享來看:轉發不僅可以進行頁面跳轉,並且該頁面可以共享request中的資源;重定向,只允許頁面跳轉,不傳送資料。
  3. 從應用場景來看:轉發主要用在使用者登入時,跳轉到指定的頁面並返回使用者資訊等資料;重定向主要應用於使用者登出,跳轉回平臺首頁或其他網站不需要登入可訪問的頁面。
  4. 從效率來看:轉發的效率會更高,重定向的效率會比較慢。

Object中有幾種方法?

  1. Clone()方法:實現物件的淺複製,需要實現cloneable介面,否則丟擲CloneNotSupportException異常
  2. getClaa()方法:final方法,用於獲取類物件,與其相同的還有另外兩種,靜態屬性.class和Class.forName(“類全路徑”);【常用】
  3. equals()方法:用於比較兩個物件的值是否一樣,而”==”是比較兩個物件是否指向同一個地址,若是則返回true
  4. toString()方法:轉為字串型別
  5. finalize()方法:該方法是在垃圾回收機制前執行,具體執行時間不清楚
  6. hashCode()方法:獲取某個物件的地址
  7. wait()方法:讓執行緒從執行中轉為睡眠狀態
  8. notify()方法:喚醒該物件上的的某個執行緒
  9. notifyAll()方法:喚醒該物件上的全部執行緒

Java常用的六大原則

  • 單一職責原則:該原則針對類來說,即一個類只負責一個職責。假如有一個類負責了兩項職責,職責T1,職責T2,當修改T1的需求發生變化需要修改T類時,會導致職責T2的故障。

優點:1. 降低類的複雜度,一個類只負責一項職責

      2. 提高類的可讀性,可維護性

      3. 降低變更引起的風險

  • 里氏替換原則:子類在繼承父類後,需重寫父類的方法,雖然沒有強制要求子類必須按照父類方法的邏輯進行,但是子類不能夠去修改父類的邏輯。

缺點:1. 程式的可移植性降低

      2. 增加了物件之間的耦合性

      3. 如果父類進行修改後,繼承它的所有子類也需要進行修改,增加成本

  •      依賴倒置原則:高層模組不依賴低層模組,二者都應該依賴其抽象;抽象不依賴細節,細節依賴於抽象。通俗的講就是,在高層模組和低層模組之間加入一個抽象(介面),通過抽象來將高層模組和低層模組進行依賴,降低耦合性。
  •      介面隔離原則:類A通過介面I依賴類B,類C通過介面I依賴類D,若對於類A和類C來說不是最小介面,則類B和類D都需要去實現他們不需要的方法,這樣會使程式變得很臃腫,採用介面隔離後,類A通過介面I依賴B,類C通過介面J依賴類D,這樣就可以減輕程式的臃腫。
  •      迪米特法則:物件之間應該減少關聯,從而降低物件之間的耦合性
  •      開閉原則:一個軟體實體類,應該對外擴充套件開放,對修改關閉,該原則時前面五個原則的基石。

 

Spring有哪些元件?

         Bean元件,Context元件,Core元件

SpringMVC執行流程

  1. 使用者傳送請求,請求被SpringMVC的前端控制器DispatcherServlet截獲
  2. DispatcherServlet得到請求的URL(統一資源定位符)並對其進行解析,得到一個URI(資源識別符號),然後根據解析到的URI來呼叫HandlerMapping進行獲取所有相關的物件。
  3. DispatcherServlet呼叫相關的HandlerAdapter進行處理。
  4. Handler處理完成後,返回一個ModelAndView給DispatcherServlet,該ModelAndView中需要包含有檢視名和檢視模型
  5. DispatcherServlet呼叫對應的檢視解析器ViewResolver並返回給DispatcherServlet
  6. ViewResolver結合Model和view渲染檢視
  7. 將檢視返回給瀏覽器

Spring IOC和AOP的區別?

  1. IOC(控制反轉Inverse of Control):假如有一個A類和一個B類,當A類需要B類時,按照我們傳統的是 B b = new B();這樣來獲取B的物件。這樣有一個缺點就是耦合性太強,假如B類的類名改成了C,那麼我們就要修改原始碼成C c = new C();Spring為了降低耦合性,出現了IOC控制反轉,若A類需要B類的物件,則不直接通過new關鍵字,而是交給Spring容器來完成,在Spring的配置檔案中可以這樣寫到 <bean id=”b” class=”com.cuc.B”/> <bean id=”a” class=”com.cuc.A”> <property name=”b” ref=”b” /></bean>,這樣就A類中直接通過定義一個變數的形式private B b;就可以動態的獲取到B類的例項化物件。
  2. AOP(面向切面程式設計):AOP主要使用在事務方面上,當你需要完成一件事情,但是在完成這件事情之前,還需要完成其他事情,比如你現在需要吃早飯,但是吃早飯的前提是你需要先刷牙和洗臉,然後吃完早飯後還需要將碗筷收拾乾淨,類似這樣的行為就是AOP,從這樣例子我們遷移到JAVA上來,AOP在事務的使用上主要是這樣的,當你需要訪問資料庫時,Sping會把在你訪問資料庫之前幫你開啟事務,在你訪問結束之後,Spring會自動的幫你提交或者回滾事務。而你並不用去理會它當中的事務處理是怎樣進行的。各自分工明確,符合單一原則的設計原則。

髒讀,不可重複讀和幻讀

  1. 髒讀:對於資料X,有一個事務A對資料X進行的修改,但是沒有修改成功,在事務回滾之前,事務B來讀取了這個事務A沒有修改成功的資料,這就是髒讀,通俗的說就是一個事務讀取到了另一個事務沒有修改成功的資料。
  2. 不可重複讀:對於資料X,事務A先讀取了資料X,然後進行事務操作,這個時候事務B對資料X進行了成功修改,然後事務A回來再次讀取資料X發現和前一次讀取到的資料不一樣,這個就是髒讀,通俗的說就是一個事務第一次讀取了資料,然後另一個事務進行了資料的修改後,最開始的那個事務再次回來讀取時發現和前面讀取的資料不一致。
  3. 幻讀:對於N條資料,事務A讀取到了這N條資料之後,事務B這時候進來添加了M條資料,這個時候事務A在讀取時發現第一次讀取的是N條資料,而第二次則是N+M條資料。通俗的說就是一個事務第一次讀取到的資料比第二次讀取到的資料少。

Volatitle和sychronized的區別

  1. Volatitle只能作用於變數上,而sychronized則可以作用於變數,方法和類。
  2. Volatitle相當於告訴JVM,CPU快取上的資料是不確定的,需要從主存上進行獲取,sychronized是則是鎖定當前的變數,除當前執行緒外,不允許其他執行緒進行訪問
  3. Volatitle不能造成執行緒阻塞,sychronized會造成執行緒阻塞
  4. Volatitle只能保證變數修改的可見性,不能保證原子性,sychronized可以保證變數修改的可見性和原子性
  5. Volatitle變數不會被編譯器進行優化,sychronized變數會被編譯器優化

如何保證執行緒安全?

  1. 原子性(Atomic):我們的JAVA程式會被作業系統編譯成組合語言,程式若不是單指令,那麼在執行一半的時候,很容易去執行了其他的程式碼,導致該執行緒暫停,這樣很容易導致資料的錯誤出現。
  2. 同步(synchronized):同步關鍵字synchronize可以使用在變數,方法和類上,該關鍵字會給程式加一個鎖,當鎖是處於鎖住的狀態時,除了當前執行緒能夠進行操作,其他執行緒都需處於就緒狀態,等該執行緒結束後,鎖會開啟,這時根據排程演算法排程下一個執行緒進入CPU操作,同步可保證資料的可見性以及原子性。
  3. 過度優化(volatitle):有了同步可以對執行緒安全有了一定的保證性,但是在很多情況下,這樣還是不夠,所以我們還可以使用volatitle關鍵字,告訴JVM在CPU快取上的資料是不確定的,直接從主存上進行獲取。

HashMap和HashTble的區別?

  1. 時間上:HashTable產生於JDK1.1,HashMap產生於JDK1.2,所以HashTable要比HashMap早一些
  2. 公開的方法:兩者都有相同的方法(Map介面:sieze()/isEmpty()/containKey()/containValue()/get()/put()/remove()/putAllMap()/clear()/keyset()/values()/entrySet()/equals()/hashCode()/toString();Cloneable介面:clone()),但是在HashTable上,還有另外兩個方法(Dictionary抽象類:elements(),其他:contains()),因為HashTable是繼承了抽象類Directionary,而HashMap是繼承了抽象類AbstractMap,但是抽象類Directionary已經被棄用了,所以element()方法也就沒啥用,而contains()方法跟前面Map介面的containValue()方式是一樣的。
  3. Null key和Null value:HashTable是不允許null值存在的,會報空指標NullPointerException異常,而HashMap則對null進行了特殊的處理,會將null的雜湊碼值定為0,也就放在了雜湊表的第一個位置。
  4. 容量:HashTable初始容量是11,每次擴大是容量是2N+1;HashMap的初始容量是16,每次擴大2N
  5. 執行緒安全:HashTable是執行緒安全的,在其get(Object key)和Keyset()方法中都使用了sychronized關鍵字,HashMap是執行緒不安全的

什麼是死鎖?

  • 死鎖的概念:產生死鎖,至少需要兩個及以上的執行緒才可以產生,執行緒對資源的使用,我在等你的執行,而你在等我,相互等待,互不相讓,則會產生死鎖的情況