每日十道面試題(八)

每天進步一點

1.什麼是淺拷貝,什麼是深拷貝

淺拷貝你可以看成是引用拷貝,就是多了個引用指向同一個內存地址,

深拷貝就是對象拷貝,你自己複製了一個內存來存放,然後新引用指向新地址

比如你盜版別人視頻,如果淺拷貝,你只盜版了一個鏈接地址,別人哪天視頻下架了,你鏈接過去也看不到

如果深拷貝的話,你下載了別人的視頻,然後自己發佈,給別人 的地址就是自己的盜版視頻地址,跟原作者怎麼改動視頻無關,但是後續更新你要一次次克隆

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object clone = super.clone();
        //深克隆 序列化,反序列化也會克隆
        Video v=(Video)clone;
        //將這個對象的屬性也進行克隆
        v.createTime = (Date) this.createTime.clone();
        return clone;
    }

ps:這裏的話我建議可以去了解一下設計模式的原型模式哦,花個5分鐘就能理解

2.JDK 和 JRE 有什麼區別?

JDK:Java Development Kit 的簡稱,java 開發工具包,提供了 java 的開發環境和運行環境。
JRE:Java Runtime Environment 的簡稱,java 運行環境,爲 java 的運行提供了所需環境。
具體來說 JDK 其實包含了 JRE,同時還包含了編譯 java 源碼的編譯器 javac,還包含了很多 java 程序調試和分析的工具。簡單來說:如果你需要運行 java 程序,只需安裝 JRE 就可以了,如果你需要編寫 java 程序,需要安裝 JDK。

一般來說jdk很多工具類最重要的就是rt.jar了根加載器會去找裏面的類,ext是擴展加載器,其它是應用加載器

3.synchronized 和 volatile 的區別是什麼?

  • volatile本質是在告訴jvm當前變量在寄存器(工作內存)中的值是不確定的,需要從主存中讀取; synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住。
  • volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別的
  • volatile僅能實現變量的修改可見性,不能保證原子性;而synchronized則可以保證變量的修改可見性和原子性。
  • volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。
  • volatile標記的變量不會被編譯器優化;synchronized標記的變量可以被編譯器優化。

你可以把synchronized 想成一個重量級鎖,而volatile是輕量級,關於volatile可以看我前幾期的面試題裏有講

4.Java 中會存在內存泄漏嗎,請簡單描述

理論上Java因爲有垃圾回收機制(GC)不會存在內存泄露問題(這也是Java被廣泛使用於服務器端編程的一個重要原因);然而在實際開發中,可能會存在無用但可達的對象,這些對象不能被GC回收,因此也會導致內存泄露的發生。例如hibernate的Session(一級緩存)還有mybatis的SqlSessionfactory中的對象屬於持久態,垃圾回收器是不會回收這些對象的,然而這些對象中可能存在無用的垃圾對象,如果不及時關閉(close)或清空(flush)一級緩存就可能導致內存泄露

這裏可以瞭解一下可達性分析,如果跟GCROOT沒關係就會被回收,下面是GCroot對象

  1. 虛擬機棧(棧幀中的本地變量表)中引用的對象。(可以理解爲:引用棧幀中的本地變量表的所有對象)
  2. 方法區中靜態屬性引用的對象(可以理解爲:引用方法區該靜態屬性的所有對象)
  3. 方法區中常量引用的對象(可以理解爲:引用方法區中常量的所有對象)
  4. 本地方法棧中(Native方法)引用的對象(可以理解爲:引用Native方法的所有對象)

5.如何實現字符串的反轉及替換?

方法很多,可以自己寫實現也可以使用String或StringBuffer/StringBuilder中的方法。有一道很常見的面試題是用遞歸實現字符串反轉,代碼如下所示:

public static String reverse(String originStr) {
      if(originStr == null || originStr.length() <= 1) 
          return originStr;
      return reverse(originStr.substring(1)) + originStr.charAt(0);
  }

或者不允許使用工具類的話,那就自己循環頭尾互換,時間是o(N)

6.列出一些你常見的運行時異常?

  • ArithmeticException(算術異常)

  • ClassCastException (類轉換異常)

  • IllegalArgumentException (非法參數異常)

  • IndexOutOfBoundsException (下標越界異常)

  • NullPointerException (空指針異常)

  • SecurityException (安全異常)

  • OOM

  • StackflowExcption

  • 併發修改異常

下面三個比較重要

7.線程的sleep()方法和yield()方法有什麼區別?

答:
① sleep()方法給其他線程運行機會時不考慮線程的優先級,因此會給低優先級的線程以運行的機會;yield()方法只會給相同優先級或更高優先級的線程以運行的機會;
② 線程執行sleep()方法後轉入阻塞(blocked)狀態,而執行yield()方法後轉入就緒(ready)狀態;
③ sleep()方法聲明拋出InterruptedException,而yield()方法沒有聲明任何異常;

④ sleep()方法比yield()方法(跟操作系統CPU調度相關)具有更好的可移植性

yield方法調用後是使線程讓出當前cpu資源而已,然後大家再競爭

8.事務的ACID是指什麼?

**原子性(Atomic):**事務中各項操作,要麼全做要麼全不做,任何一項操作的失敗都會導致整個事務的失敗;
一致性(Consistent):事務結束後系統狀態是一致的;
隔離性(Isolated):併發執行的事務彼此無法看到對方的中間狀態;
持久性(Durable):事務完成後所做的改動都會被持久化,即使發生災難性的失敗。通過日誌和同步備份可以在故障發生後重建數據。

9.Servlet的運行過程?(生命週期)

Web容器加載Servlet並將其實例化後,Servlet生命週期開始,容器運行其init()方法進行Servlet的初始化;請求到達時調用Servlet的service()方法,service()方法會根據需要調用與請求對應的doGet或doPost等方法;當服務器關閉或項目被卸載時服務器會將Servlet實例銷燬,此時會調用Servlet的destroy()方法。

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

forward是容器中控制權的轉向,是服務器請求資源,服務器直接訪問目標地址的URL,把那個URL 的響應內容讀取過來,然後把這些內容再發給瀏覽器,瀏覽器根本不知道服務器發送的內容是從哪兒來的,所以它的地址欄中還是原來的地址。redirect就是服務器端根據邏輯,發送一個狀態碼,告訴瀏覽器重新去請求那個地址,因此從瀏覽器的地址欄中可以看到跳轉後的鏈接地址,很明顯redirect無法訪問到服務器保護起來資源,但是可以從一個網站redirect到其他網站。forward更加高效,所以在滿足需要時儘量使用forward(通過調用RequestDispatcher對象的forward()方法,該對象可以通過ServletRequest對象的getRequestDispatcher()方法獲得),並且這樣也有助於隱藏實際的鏈接;在有些情況下,比如需要訪問一個其它服務器上的資源,則必須使用重定向(通過HttpServletResponse對象調用其sendRedirect()方法實現)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章