主頁 > 後端開發 > 這13道面試題,哪怕背你也要背過來。別說我沒提醒你

這13道面試題,哪怕背你也要背過來。別說我沒提醒你

2020-09-11 23:16:10 後端開發

前言:

最近有網友后臺私信我,你天天更新的不是大廠就還是TM的大廠,整的我看到那些面試題一臉懵逼,都沒有信心了,現在我都水平有限,有沒有樸實一點的面試題提供參考一下啊,

好的,今天他來了

在這里插入圖片描述

1、在多執行緒環境中使用HashMap會有什么問題?在什么情況下使用get()方法會產生無限回圈?

HashMap本身沒有什么問題,有沒有問題取決于你是如何使用它的,比如,你在一個執行緒里初始化了一個HashMap然后在多個其他執行緒里對其進行讀取,這肯定沒有任何問題,有個例子就是使用HashMap來存盤系統配置項,當有多于一個執行緒對HashMap進行修改操作的時候才會真正產生問題,比如增加、洗掉、更新鍵值對的時候,因為put()操作可以造成重新分配存盤大小(re-sizeing)的動作,因此有可能造成無限回圈的發生,所以這時需要使用Hashtable或者ConcurrentHashMap,而后者更優,

2、不重寫Bean的hashCode()方法是否會對性能帶來影響?

這個問題非常好,每個人可能都會有自己的體會,按照我掌握的知識來說,如果一個計算hash的方法寫得不好,直接的影響是,當向HashMap中添加元素的時候會更頻繁地造成沖突,因此最終增加了耗時,但是自從Java 8開始,這種影響不再像前幾個版本那樣顯著了,因為當沖突的發生超出了一定的限度之后,鏈表類的實作將會被替換成二叉樹(binary tree)實作,這時你仍可以得到O(logN)的開銷,優于鏈表類的O(n),

3、對于一個不可修改的類,它的每個物件是不是都必須宣告成final的?

不盡然,因為你可以通過將成員宣告成非final且private,并且不要在除了建構式的其他地方來修改它,不要為它們提供setter方法,同時不會通過任何函式泄露出對此成員的參考,需要記住的是,把物件宣告成final僅僅保證了它不會被重新賦上另外一個值,你仍然可以通過此參考來修改參考物件的屬性,這一點是關鍵,面試官通常喜歡聽到你強調這一點,

4、String的substring()方法內部是如何實作的?

又一個Java面試的好問題,你應該答出“substring方法通過原字串創建了一個新的物件”,否則你的回答肯定是不能令人滿意的,這個問題也經常被拿來測驗應聘者對于substring()可能帶來的記憶體泄漏風險是否有所了解,直到Java 1.7版本之前,substring會保存一份原字串的字符陣列的參考,這意味著,如果你從1GB大小的字串里截取了5個字符,而這5個字符也會阻止那1GB記憶體被回收,因為這個參考是強參考,

5、你在寫存盤程序或者在Java里呼叫存盤程序的時候如何來處理錯誤情況?

這是個很棘手的Java面試題,答案也并不固定,我的答案是,寫存盤程序的時候一旦有操作失敗,則一定要回傳錯誤碼,但是在呼叫存盤程序的時候出錯的話捕捉SQLException卻是唯一能做的,

6、Java 中新的 Lock 介面相對于同步代碼塊(synchronized block)有什么優勢?如果讓你實作一個高性能快取,支持并發讀取和單一寫入,你如何保證資料完整性,

多執行緒和并發編程中使用 lock 介面的最大優勢是它為讀和寫提供兩個單獨的鎖,可以讓你構建高性能資料結構,比如 ConcurrentHashMap 和條件阻塞,
這道 Java 執行緒面試題越來越多見,而且隨后的面試題都基于面試者對這道題的回答,
我強烈建議在任何 Java 多執行緒面試前都要多看看有關鎖的知識,因為如今電子交易系統的客戶端和資料互動中,鎖被頻繁使用來構建快取,

7、Executor.submit()和Executor.execute()這兩個方法有什么區別?

前者回傳一個Future物件,可以通過這個物件來獲得作業執行緒執行的結果,
當我們考察例外處理的時候,又會發現另外一個不同,當你使用execute提交的任務拋出例外時,此例外將會交由未捕捉例外處理程序來處理(uncaught exception handler),當你沒有顯式指定一個例外處理器的話,默認情況下僅僅會通過System.err列印出錯誤堆疊,當你用submit來提交一個任務的時候,這個任務一旦拋出例外(無論是否是運行時例外),那這個例外是任務回傳物件的一部分,對這樣一種情形,當你呼叫Future.get()方法的時候,這個方法會重新拋出這個例外,并且會使用ExecutionException進行包裝,

8、能否寫一段用Java 4或5來遍歷一個HashMap的代碼?

事實上,用Java可以有四種方式來遍歷任何一個Map,一種是使用keySet()方法獲取所有的鍵,然后遍歷這些鍵,再依次通過get()方法來獲取對應的值,第二種方法可以使用entrySet()來獲取鍵值對的集合,然后使用for each陳述句來遍歷這個集合,遍歷的時候獲得的每個鍵值對已經包含了鍵和值,這種算是一種更優的方式,因為每輪遍歷的時候同時獲得了key和value,無需再呼叫get()方法,get()方法在那種如果bucket位置有一個巨大的鏈表的時候的性能開銷是O(n),第三種方法是獲取entrySet之后用iterator依次獲取每個鍵值對,第四種方法是獲得key set之后用iterator依次獲取每個key,然后再根據key來呼叫get方法,

9、你在什么時候會重寫hashCode()和equals()方法?

當你需要根據業務邏輯來進行相等性判斷、而不是根據物件相等性來判斷的時候你就需要重寫這兩個函式了,例如,兩個Employee物件相等的依據是它們擁有相同的emp_id,盡管它們有可能是兩個不同的Object物件,并且分別在不同的地方被創建,同時,如果你準備把它們當作HashMap中的key來使用的話,你也必須重寫這兩個方法,現在,作為Java中equals-hashcode的一個約定,當你重寫equals的時候必須也重寫hashcode,否則你會打破諸如Set, Map等集合賴以正常作業的約定,你可以看看我的另外一篇博文來理解這兩個方法之間的微妙區別與聯系,

10、如果不重寫hashCode方法會有什么問題?

如果不重寫equals方法的話,equals和hashCode之間的約定就會被打破:當通過equals方法回傳相等的兩個物件,他們的hashCode也必須一樣,如果不重寫hashCode方法的話,即使是使用equals方法回傳值為true的兩個物件,當它們插入同一個map的時候,因為hashCode回傳不同所以仍然會被插入到兩個不同的位置,這樣就打破了HashMap的本來目的,因為Map本身不允許存進去兩個key相同的值,當使用put方法插入一個的時候,HashMap會先計算物件的hashcode,然后根據它來找到存盤位置(bucket),然后遍歷此存盤位置上所有的Map.Entry物件來查看是否與待插入物件相同,如果沒有提供hashCode的話,這些就都做不到了,

11、HashMap,在呼叫get()方法的時候equals()和hashCode()方法都起了什么樣的作用?

應聘者應該知道的是,一旦你提到了hashCode()方法,人們很可能要問HashMap是如何使用這個函式的,當你向HashMap插入一個key的時候,首先,這個物件的hashCode()方法會被呼叫,呼叫結果用來計算將要存盤的位置(bucket),

因為某個位置上可能以鏈表的方式已經包含了多個Map.Entry物件,所以HashMap會使用equals()方法來將此物件與所有這些Map.Entry所包含的key進行對比,以確定此key物件是否已經存在,

12、在Java中如何避免死鎖?

你可以通過打破互相等待的局面來避免死鎖,為了達到這一點,你需要在代碼中合理地安排獲取和釋放鎖的順序,如果獲得鎖的順序是固定的,并且獲得的順序和釋放的順序剛好相反的話,就不會產生出現死鎖的條件了,

13、說說ClassLoader.loadClass()與Class.forName()的區別

ClassLoader.loadClass()與Class.forName()大家都知道是反射用來構造類的方法,但是他們的用法還是有一定區別的,
在講區別之前,我覺得很有不要把類的加載程序在此整理一下,
在Java中,類裝載器把一個類裝入Java虛擬機中,要經過三個步驟來完成:裝載、鏈接和初始化,其中鏈接又可以分成校驗、準備和決議三步,除了決議外,其它步驟是嚴格按照順序完成的,各個步驟的主要作業如下:

  • 裝載:查找和匯入類或介面的二進制資料;
  • 鏈接:執行下面的校驗、準備和決議步驟,其中決議步驟是可以選擇的;
  • 校驗:檢查匯入類或介面的二進制資料的正確性;
  • 準備:給類的靜態變數分配并初始化存盤空間;
  • 決議:將符號參考轉成直接參考;
  • 初始化:激活類的靜態變數的初始化Java代碼和靜態Java代碼塊,

于是乎我們可以開始看2者的區別了,

Class.forName(className)方法,其實呼叫的方法是Class.forName(className,true,classloader);注意看第2個boolean引數,它表示的意思,在loadClass后必須初始化,比較下我們前面準備jvm加載類的知識,我們可以清晰的看到在執行過此方法后,目標物件的 static塊代碼已經被執行,static引數也已經被初始化,

再看ClassLoader.loadClass(className)方法,其實他呼叫的方法是ClassLoader.loadClass(className,false);還是注意看第2個 boolean引數,該引數表示目標物件被裝載后不進行鏈接,這就意味這不會去執行該類靜態塊中間的內容,因此2者的區別就顯而易見了,

最后還有必要在此提一下new方法和newInstance方法的區別

  • newInstance: 弱型別,低效率,只能呼叫無參構造,
  • new: 強型別,相對高效,能呼叫任何public構造,

例如,在JDBC編程中,常看到這樣的用法,Class.forName(“com.mysql.jdbc.Driver”),如果換成了 getClass().getClassLoader().loadClass(“com.mysql.jdbc.Driver”),就不行,
為什么呢?打開com.mysql.jdbc.Driver的源代碼看看

static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
} 

Driver在static塊中會注冊自己到java.sql.DriverManager,而static塊就是在Class的初始化中被執行,所以這個地方就只能用Class.forName(className),

最后

面試難免讓人焦慮不安,經歷過的人都懂的,但是如果你提前預測面試官要問你的問題并想出得體的回答方式,就會容易很多,

所以,加油準備吧,需要更多面試資料的朋友,來我的碼云查看吧: https://gitee.com/biwangsheng/personal.git

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/8267.html

標籤:Java

上一篇:討論下簡道云平臺

下一篇:阿里餓了么Java4面:(資料結構+框架原始碼+JVM+分布式)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more