就因為沒看這篇文章面試失敗了

知識追尋者發表於2020-07-26

前言

熬夜整理了一份java基礎面試題,希望大家支援,如果文中有錯誤希望大家指正;

公眾號:知識追尋者

知識追尋者(Inheriting the spirit of open source, Spreading technology knowledge;)

一 java基礎面試

1.1物件導向和麵向過程的區別

  • 程式導向:

優點:效能比物件導向高,因為類呼叫時需要例項化,開銷比較大,比較消耗 資源

應用場景:微控制器、嵌入式開發、Linux/Unix ;

缺點:沒有物件導向易維護、易複用、易擴充套件

  • 物件導向

優點:因為物件導向有封裝、繼承、多型性的特 性,可以設計出低耦合的系統,故易維護、易複用、易擴充套件;

應用場景:網頁開發,後臺開發等;

缺點:效能比程式導向低

1.2 物件導向的特性

  • 封裝: 將一個物件的屬性私有化,並提供一個對外訪問的方法;
  • 繼承:在已有類的基礎上建立新類;提供繼承資訊的類被稱為父類(超類、基類);得到繼 承資訊的類被稱為子類(派生類)
  • 多型:一個物件的多種表現形態;用同樣的物件引用呼叫同樣的方法但是做了不同的事情;可以向上轉型和向下轉型

多型實現形式:

重寫:子類對父類方法的重寫;

覆蓋:實現介面,並覆蓋方法;

1.3 抽象

抽象是指將物件抽象為具體類的過程;抽象只關注物件有哪些屬性和行為(方法);

1.4 Java語言特點

  1. 簡單易學;
  2. 物件導向(封裝,繼承,多型);
  3. 跨平臺(Java虛擬機器實現平臺無關性);
  4. 可靠性;
  5. 安全性;
  6. 支援多執行緒
  7. 支援編譯與解釋;
  8. 支援網路程式設計

1.5 JDK,JRE,JVM之間的區別

JDK: java開發工具包;包含JRE, javac等調優診斷工具;能夠建立和編譯程式;

JRE: java執行環境; 包括 Java 虛擬機器(JVM),Java 類庫,java 命令和其他的一些基礎構件;不能建立程式;

JVM:java虛擬機器,提供執行位元組碼檔案(.class)的環境支援;

jdk 包含jre ; jre 包含 jvm

1.6 物件導向五大基本原則

  • 單一職責原則SRP(Single Responsibility Principle);設計類時要功能單一;
  • 開放封閉原則OCP(Open-Close Principle);一個模組對於擴充是開放的,對於修改是封閉;
  • 裡式替換原則LSP(the Liskov Substitution Principle LSP);子類可以替換父類;
  • 依賴倒置原則DIP(the Dependency Inversion Principle DIP);高層次的模組不應該依賴於低層次的模組,他們都應該依賴於抽象。抽象不應該依賴於具體實現,具體實現應該依賴於抽象;
  • 介面分離原則ISP(the Interface Segregation Principle ISP);設計類時,功能介面拆分為多個;

開發設計類時需考慮的事情,面試中如果碰見能答幾個就幾個;

1.7 什麼是java主類

java主類是java程式碼執行的入口,即包含 main方法的類;

1.8 構造器能否被重寫

子類無法繼承父類的構造器,所以構造器不能被重寫(overidde),但可以被過載(overload);

1.9 過載和重寫的區別

重寫 :

  • 發生在父類與子類之間

  • 方法名,引數列表,必須相同,返回值小於等於父類;

  • 訪問修飾符大於等於父類(public>protected>default>private);父類方法為private,則無法重寫;

  • 重丟擲異常的範圍要小於等於父類異常;

過載

  • 發生在同一個類中
  • 方法名相同引數列表不同(引數型別不同、個數不同、順序不同);
  • 方法返回值和訪問修飾符可以不同;

1.10 equals與==的區別

== : 判定是否是相同一個物件 ,比較的是變數(棧)記憶體中存放的物件的(堆)記憶體地址,用來判斷兩個物件的地址是否相同,;

equals: equals用來比較的是兩個物件的內容是否相等; 但Object中的equals方法返回的卻是==的判斷

1.11什麼是hashCode

hashCode() 的作用是獲取雜湊碼,也稱為雜湊碼;它實際上一個int整數;雜湊碼的作用是確定該物件在雜湊表中的索引位置;雜湊表儲存的是鍵值對(key-value),即能根據鍵獲取值;

當一個物件插入雜湊表時先會比較物件與雜湊表中已有的物件hash值,若不同,則直接插入雜湊表,若相同(hash碰撞),則會呼叫equals 方法檢查是否真的相同, 如果equal()判斷不相等,直接將該元素放入集合中,否則不放入;

物件中hashCode()與equals()的關係

  • 如果兩個物件相等,則hashcode也相等;
  • 兩個物件相等,對兩個物件分別呼叫equals方法都返回true
  • 兩個物件有相同的hashcode值,它們不一定是同一個物件;
  • equals 方法被覆蓋過,則 hashCode 方法也必須被覆蓋;

1.12 什麼是值傳遞和引用傳遞

值傳遞:傳遞了物件的一個副本,即使副本被改變,也不會影響源物件;

引用傳遞:著傳遞的並不是實際的物件,而是物件的引用;對外部物件的改變會反映到實際物件;

一般認為,Java 內的傳遞都是值傳遞,Java 中例項物件的傳遞是引用傳遞;

1.13 什麼是抽象類與介面

  • 抽象類是對類的抽象,是一種模板設計; 而介面是行為的抽象,可以理解為行為的規範;

  • 抽象類中可以包含非抽象方法;而介面是絕對的抽象方法;

  • 介面預設是public 方法,java8中介面支援預設(default)方法;

  • 一個類可以實現多個介面,但只能實現一個抽象類;

  • 抽象類不能使用final修飾(final修飾的類為固定類,無法被繼承)

1.14String、String StringBuffer 和 StringBuilder 的區別

  • String是隻讀字串,並不是基本資料型別,而是一個物件;其無法改變;每次操作都會產生新物件;
  • StringBuilder 並沒有對方法進行加同步鎖,執行緒不安全;
  • StringBuffer 對方法加了同步鎖,執行緒安全;

tip: 資料量少的時候使用 String; 單執行緒使用StringBuilder ; 多執行緒使用 StringBuffer ; 使用StringBuilder 效能比 StringBuffer 效能 提升大概有 10%~15%;

1.15 用最有效率的方法計算 2 乘以 8

2 << 3 = 8 ; 2 左移3位

1.16 & 與 && 的區別

& 運算子 按位與;

&& 運算子是短路與:&& 左邊的表示式的值是 false,右邊的表示式會被直接短路掉,不會進行運算

1.17 static 關鍵字

static 變數在 Java 中屬於類的,它在所有的例項中具有相同的值。當類被 Java 虛擬機器載入的時候,會對 static 變數進行初始化;故需要用例項來訪問 static 變數;

1.18 Java 支援的資料型別

  1. 整數值型:byte,short,int,long;
  2. 字元型:char;
  3. 浮點型別:float,double;
  4. 布林型:boolean;
型別 位數 位元組數
short 2 16
int 4 32
long 8 64
float 4 32
double 8 64
char 2 16

1.19 final, finally, finalize 的區別

  • final:用於宣告屬性,方法和類, 分別表示屬性不可變, 方法不可覆蓋, 類不可繼承.
  • finally:異常處理語句結構的一部分,表示最後總是會執行.
  • finalize:Object類的一個方法,在垃圾收集器執行的時候會呼叫被回收物件的此方法;

1.20 instanceof 關鍵字

instanceof 嚴格來說是Java中的一個雙目運算子,用來檢查一個物件是否為一個類的例項;

1.21 為什麼不能用浮點型表示金額

浮點數為非精確值,應該使用BigDecimal來修飾金額;

1.22 自動裝箱與拆箱

  • 裝箱:自動將基本資料型別轉換為包裝器型別,呼叫 Integer的valueOf(int) 方法;
  • 拆箱:自動將包裝器型別轉換為基本資料型別。呼叫Integer的intValue方法

tip: int 是基礎資料型別,佔用空間小; Integer 是物件佔用空間大;

1.23 switch中能否使用string做引數

在idk 1.7之前,switch只能支援byte, short, char, int或者其對應的封裝類以及Enum型別。從idk 1.7之後switch開始支援String。

可以用在byte上,但是不能用在long上。

1.24 java 建立物件的幾種方式

  1. 採用new
  2. 通過反射
  3. 採用clone
  4. 通過序列化機制

1.25 如何將byte轉為String

可以使用 String 接收 byte[] 引數的構造器來進行轉換, 但編碼必須正確;

1.26 final有哪些用法

1.被final修飾的類不可以被繼承
2.被final修飾的方法不可以被重寫
3.被final修飾的變數不可以被改變。
5.被final修飾的常量,在編譯階段會存入常量池中。

1.27 java當中的四種引用

  1. 強引用:如果一個物件具有強引用,它就不會被垃圾回收器回收。即使當前記憶體空間不足,JVM也不會回收它,而是丟擲 OutOfMemoryError 錯誤,使程式異常終止。如果想中斷強引用和某個物件之間的關聯,可以顯式地將引用賦值為null,這樣一來的話,JVM在合適的時間就會回收該物件。
  2. 軟引用:在使用軟引用時,如果記憶體的空間足夠,軟引用就能繼續被使用,而不會被垃圾回收器回收,只有在記憶體不足時,軟引用才會被垃圾回收器回收。
  3. 弱引用:具有弱引用的物件擁有的生命週期更短暫。因為當 JVM 進行垃圾回收,一旦發現弱引用物件,無論當前記憶體空間是否充足,都會將弱引用回收。
  4. 虛引用:如果一個物件僅持有虛引用,那麼它相當於沒有引用,在任何時候都可能被垃圾回收器回收。

1.28 Math. round(-1. 5) 等於多少?

Math.round(-1.5)的返回值是-1。四捨五入的原理是在引數上加0.5然後做向下取整

1.29 String str="i"與 String str=new String("i")一樣嗎?

tring str="i"的方式,Java 虛擬機器會將其分配到常量池中;而 String str=new String("i") 則會被分到堆記憶體中;所以一個是常量,一個是物件,不一樣;

1.30char 型變數中能不能儲存一箇中文漢字

char 型別可以儲存一箇中文漢字,因為 Java 中使用的編碼是 Unicode,一個 char 型別佔 2 個位元組,所以能放一箇中文。

1.31 break 和 continue 的區別

  • break 跳出整個迴圈。
  • continue 用於跳過本次迴圈,執行下次迴圈。

1.32 內部類與靜態內部類的區別

內部類:
1、內部類中的變數和方法不能宣告為靜態。
2、內部類例項化:B是A的內部類,例項化B:A.B b = new A().new B()
3、內部類可以引用外部類的靜態或者非靜態屬性及方法。

靜態內部類:
1、靜態內部類屬性和方法可以宣告為靜態的或者非靜態的。
2、例項化靜態內部類:B是A的靜態內部類,A.B b = new A.B()
3、靜態內部類只能引用外部類的靜態的屬性及方法。

1.33 throw和throws的區別?

  • throw用於主動丟擲java.lang.Throwable 類的一個例項化物件,即通過關鍵字 throw 丟擲一個 Error 或者 一個Exception;
  • throws 的作用是作為方法宣告和簽名的一部分;

1.34 error和exception的區別

  • Error類和Exception類的父類都是throwable類
  • Error類一般是指與虛擬機器相關的問題,如系統崩潰,虛擬機器錯誤,記憶體空間不足,方法呼叫棧溢等。直接終止程式即可;
  • Exception類表示程式可以處理的異常,可以捕獲和有可能恢復。需要程式設計師手動處理;

1.35 什麼時候用斷言(assert)

斷言是一個包含布林表示式的語句,在執行這個語句時假定該表示式為true;如果表示式的值為false,那麼系統會報告一個AssertionError。

斷言有兩種形式:

  • assert Expression1;表示一個boolean表示式
  • assert Expression1 : Expression2; Expression2表示一個基本型別、表示式或者是一個Object,用於在失敗時輸出錯誤資訊
assert false;
assert i == 0:"123";// 當 i不等於0 時會輸出錯誤資訊

1.36 常見的五種執行時異常

  • ClassCastException(類轉換異常)
  • IndexOutOfBoundsException(陣列越界)
  • NullPointerException(空指標異常)
  • ArrayStoreException(資料儲存異常,運算元組是型別不一致)
  • BufferOverflowException(快取溢位異常)

二 IO流面試

2.1 序列化的含義

  • 序列化:將物件寫入到IO流中
  • 反序列化:從IO流中恢復物件

序列化機制將序列化的Java物件轉換為位位元組序列,這些位元組序列可以儲存在磁碟上,或通過網路傳輸,以達到以後恢復成原來的物件,通常被序列化的要實現Serializable介面,並指定序列值

Externalizable 可以控制整個序列化過程,指定特定的二進位制格式,增加安全機制

2.2 java 中 IO 流分類

  • 按照流的流向分,可以分為輸入流和輸出流;

  • 按照操作單元劃分,可以劃分為位元組流和字元流;

  • 按照流的角色劃,可以分為節點流和處理流。

  • InputStream/Reader: 所有的輸入流的基類,前者是位元組輸入流,後者是字元輸入流。

  • OutputStream/Writer: 所有輸出流的基類,前者是位元組輸出流,後者是字元輸出流。

圖片來源網路:

2.3 BIO、NIO、AIO的區別

  1. BIO 就是傳統的 java.io 包,它是基於流模型實現的,互動的方式是同步、阻塞方式IO; 在讀入輸入流或者輸出流時,在讀寫完成之前,執行緒會一直處於阻塞狀態。
  2. NIO (New IO)是 Java 1.4 引入的 java.nio 包,提供了 Channel、Selector、Buffer 等新的抽象,可以構建多路複用的、同步非阻塞 IO 程式。
  3. AIO(Asynchronous IO) 是 Java 1.7 之後引入的包,是 NIO 的升級版本,提供了非同步非堵塞的 IO 操作方式,所以人們叫它 AIO,非同步 IO 是基於事件和回撥機制實現。

三 集合面試

3.1 java 集合架構

3.2 Collection 和 Collections的區別

Collection:是java.uitl 下的介面,他是各種集合的父介面;

Conllecitons:是個java.util下的類,是針對集合的工具類,提供一系列靜態方法對集合的搜尋、查詢、同步等操作;

3.3 ArrayList和Vector的區別

  • 共同點:都實現了List介面,為有序的集合,底層基於陣列實現,通過索引取值,允許元素重複和為null;都是實現 fail-fast機制;
  • 區別:ArrayList不同步,Vector是同步(ArrayList 比 Vector 快,不會過載);Vector擴容原來的一倍,ArrayList擴容原來的0.5倍;

3.4List,Set,Map 三者的區別?

  • List: 儲存的元素有序可重複。
  • Set: 儲存的元素是無序的、不可重複的。
  • Map: 使用鍵值對(kye-value)儲存,通過key 獲取value; key 不能重複;

3.5 ArrayList,LinkedList區別

共同點:

ArrayListLinkedList 都是執行緒不安全;

區別:

  • ArrayList的底層是陣列實現,LinkedList的底層是雙向連結串列實現。
  • ArrayList 通過索引獲取值,查詢快;LinkedList通過遍歷連結串列獲取值查詢慢;
  • ArrayList 增刪慢,LinkedList 增刪快;

3.6Enumeration和iterator介面的區別

  • iterator是Enumeration介面的替代品,只提供了遍歷vector和HashTable型別集合元素的功能;
  • Enumeration速度是iterator的2倍,同時佔用更少的記憶體。
  • terator有fail-fast機制,比Enumeration更安全
  • Iterator能夠刪除元素,Enumeration並不能刪除元素

3.7 簡述Iterator 迭代器

Iterator迭代器可以對集合進行遍歷, 遍歷方式都是 hasNext()next()方法,,在當前遍歷集合元素被更改的時候,就會丟擲 ConcurrentModificationException 異常;

3.8 HashMap和Hashtable的區別

共同點: 都實現 Map介面;

區別:

  • HashMap不同步;Hashtable同步;HashMap效率比Hashtable高;
  • HashMap允許為null ;Hashtable不允許為null
  • Hashtable 預設的初始大小為 11,之後每次擴充,容量變為原來的 2n+1,HashMap 預設的初始化大小為 16;
  • HashMap 在 jdk1.8 改變了資料結構為 陣列 + 連結串列 + 紅黑樹方式; HashTable使用全表鎖,效率低下;

3.9HashSet 和 HashMap 的區別

  • HashMap 實現了Map介面;HashSet實現了Set介面
  • HashMap儲存鍵值對;HashSet僅僅儲存物件
  • HashMap使用put()方法將元素放入map中;HashSet使用add()方法將元素放入set中;
  • HashMap中使用鍵物件來計算hashcode值;ashSet使用成員物件來計算hashcode值;
  • HashSet較HashMap來說比較慢;

3.10 HashMap和TreeMap區別

TreeMap實現SortMap介面,能夠將記錄根據鍵排序(預設升序排序),也可以指定排序的比較器Comparator,當用Iterator 遍歷TreeMap時得到排序後的結果;

對於插入、刪除和定位元素等操作,選擇HashMap;如果對一個有序的key集合進行遍歷,選擇TreeMap

3.11 併發集合和普通集合區別

併發集合常見的有 ConcurrentHashMapConcurrentLinkedQueueConcurrentLinkedDeque 等。併發集合位於 java.util.concurrent 包下,是 jdk1.5 之後才有;其相比與普通集合新增了 synchronized 同步鎖,執行緒安全,但效率低;

3.12 ConcurrentHashMap1.7和1.8的區別

jdk1.8的實現不再使用jdk1.7的Segment+ HashEntry分段鎖機制實現,利用Node陣列+CAS+Synchronized來保證執行緒安全;底層採用陣列+連結串列+紅黑樹的儲存結構;

ConcurrentHashMap1.7

dk1.7

ConcurrentHashMap1.8

3.13HashMap 的長度為什麼是2的冪次方

目的是為了能讓 HashMap 存取高效,儘量減少Hash碰撞,儘量使Hash演算法的結果均勻分佈,每個連結串列/紅黑樹長度大致相同;

演算法實際是取模,hash%length,計算機中求餘效率不如位移運算,原始碼中做了優化hash&(length-1);
hash%length==hash&(length-1)的前提是length是2的n次方

3.14 ArrayList集合如何高效加入10萬條資料

直接在初始化的時候就指定ArrayList的容量值;

3.15 如何選用集合

根據集合的特點來選用集合;根據鍵獲取值選用 Map 介面下的集合;需要排序選擇 TreeMap,不需要排序選擇 HashMap,需要執行緒安全選 ConcurrentHashMap

只存放元素值時,就選擇實現Collection 介面的集合;需要元素唯一時選擇實現 Set 介面的集合,如TreeSetHashSet; 不需要元素唯一性就選擇實現 List 介面,如 ArrayListLinkedList;

3.16 快速失敗(fail-fast)和安全失敗(fail-safe)的區別是什麼

  • 快速失敗:當你在迭代一個集合的時候,如果有另一個執行緒正在修改你正在訪問的那個集合時,就會丟擲一個 ConcurrentModification 異常。 在 java.util 包下的都是快速失敗。

  • 安全失敗:你在迭代的時候會去底層集合做一個拷貝,所以你在修改上層集合的時候是不會受影響的,不會丟擲 ConcurrentModification 異常。在java.util.concurrent 包下的全是安全失敗的。

附:

HashMap 原始碼分析: https://blog.csdn.net/youku1327/article/details/105332136;

ArrayList原始碼分析https://blog.csdn.net/youku1327/article/details/105314040

tip: 需要懂 HashMap,ArrayList,LinkedList,ConcurrentHashMap底層實現原理

相關文章