1. 程式人生 > >Java面試2018常考題目彙總(一)

Java面試2018常考題目彙總(一)

因為最近在忙著找工作,看到了很多面試整理的文章,於是便有了自己也寫一篇,部分原創,大部分是我四處蒐集的,我想整理一份最全最新的文章,方便大家總結!廢話不多說,開始!

一、JAVA基礎篇-概念

1.簡述你所知道的Linux:

Linux起源於1991年,1995年流行起來的免費作業系統,目前, Linux是主流的伺服器作業系統, 廣泛應用於網際網路、雲端計算、智慧手機(Android)等領域。由於Java主要用於伺服器端的開發,因此Java應用的部署環境有很多為Linux。
Windows作業系統的目錄結構,是以碟符為單位,C盤、D盤、E盤等等,資料儲存在各個碟符之下,而Linux作業系統最頂層只有一個根目錄root,所有檔案都儲存在這一個根目錄之下。
Linux不像Windows的圖形操作介面,是通過命令的方式進行操作,常用命令有:
a . pwd:用於顯示當前工作目錄;
b . ls:用於檢視當前工作目錄內容;
c . cd:用於改變當前工作目錄。

2.什麼是Java虛擬機器?為什麼Java被稱作是“平臺無關的程式語言”?

Java虛擬機器是一個可以執行Java位元組碼的虛擬機器程序。Java原始檔被編譯成能被Java虛擬機器執行的位元組碼檔案。
Java被設計成允許應用程式可以執行在任意的平臺,而不需要程式設計師為每一個平臺單獨重寫或者是重新編譯。Java虛擬機器讓這個變為可能,因為它知道底層硬體平臺的指令長度和其他特性。

3.JDK、JRE、JVM關係是什麼?

JDK(Java Development Kit)即為Java開發工具包,包含編寫Java程式所必須的編譯、執行等開發工具以及JRE。開發工具如:用於編譯java程式的javac命令、用於啟動JVM執行java程式的java命令、用於生成文件的javadoc命令以及用於打包的jar命令等等。
JRE(Java Runtime Environment)即為Java執行環境,提供了執行Java應用程式所必須的軟體環境,包含有Java虛擬機器(JVM)和豐富的系統類庫。系統類庫即為java提前封裝好的功能類,只需拿來直接使用即可,可以大大的提高開發效率。
JVM(Java Virtual Machines)即為Java虛擬機器,提供了位元組碼檔案(.class)的執行環境支援。
簡單說,就是JDK包含JRE包含JVM。

4.Java支援的資料型別有哪些?什麼是自動拆裝箱?

基本資料型別:
整數值型:byte,short,int,long,
字元型:char
浮點型別:float,double
布林型:boolean
整數預設int型,小數預設是double型。Float和long型別的必須加字尾。

首先知道String是引用型別不是基本型別,引用型別宣告的變數是指該變數在記憶體中實際儲存的是一個引用地址,實體在堆中。引用型別包括類、介面、陣列等。String類還是final修飾的。
而包裝類就屬於引用型別,自動裝箱和拆箱就是基本型別和引用型別之間的轉換,至於為什麼要轉換,因為基本型別轉換為引用型別後,就可以new物件,從而呼叫包裝類中封裝好的方法進行基本型別之間的轉換或者toString(當然用類名直接呼叫也可以,便於一眼看出該方法是靜態的),還有就是如果集合中想存放基本型別,泛型的限定型別只能是對應的包裝型別。

5.面向物件是什麼?

面向物件是一種思想,世間萬物都可以看做一個物件,這裡只討論面向物件程式設計(OOP),Java是一個支援併發、基於類和麵向物件的計算機程式語言,面向物件軟體開發的優點:
程式碼開發模組化,更易維護和修改;
程式碼複用性強;
增強程式碼的可靠性和靈活性;
增加程式碼的可讀性。
  • 面向物件的四大基本特性:

抽象:提取現實世界中某事物的關鍵特性,為該事物構建模型的過程。對同一事物在不同的需求下,需要提取的特性可能不一樣。得到的抽象模型中一般包含:屬性(資料)和操作(行為)。這個抽象模型我們稱之為類。對類進行例項化得到物件。

封裝:封裝可以使類具有獨立性和隔離性;保證類的高內聚。只暴露給類外部或者子類必須的屬性和操作。類封裝的實現依賴類的修飾符(public、protected和private等)

繼承:對現有類的一種複用機制。一個類如果繼承現有的類,則這個類將擁有被繼承類的所有非私有特性(屬性和操作)。這裡指的繼承包含:類的繼承和介面的實現。

多型:多型是在繼承的基礎上實現的。多型的三個要素:繼承、重寫和父類引用指向子類物件。父類引用指向不同的子類物件時,呼叫相同的方法,呈現出不同的行為;就是類多型特性。多型可以分成編譯時多型和執行時多型。

抽象、封裝、繼承和多型是面向物件的基礎。在面向物件四大基礎特性之上,我們在做面向物件程式設計設計時還需要遵循有一些基本的設計原則。

  • 面向物件的七大設計原則:

SOLID原則(單一職責原則、開放關閉原則、里氏替換原則、介面隔離原則和依賴倒置原則)
迪米特法則
組合優於繼承原則(合成複用原則)。
在遵循這些面向物件設計原則基礎上,前輩們總結出一些解決不同問題場景的設計模式,以四人幫的gof23最為知名。

  • 24種設計模式(gof23+1):

建立型模式:
1.簡單工廠模式(不包含在gof23中)
2.工廠模式
3.抽象工廠模式
4.單例模式
5.原型模式
建立者模式
6.結構型模式:
7.組合模式
8.裝飾者模式
9.外觀模式
10.介面卡模式
11.代理模式
12.享元模式
13.橋接模式
行為型模式:
14.觀察者模式
15.策略模式
16.狀態模式
17.中介模式
18.模板方法
19.命令模式
20.備忘錄模式
21.訪問者模式
22.直譯器模式
23.迭代器模式
24.職責鏈模式
這裡只是簡單描述了定義和特徵以及設計模式的關係,具體細節不討論。

6.請寫出下面幾個表示式的結果,答案可以用10進位制或16進制書寫

1). 0xaa | 0x55
2). 15 & 240
3). 10 ^ 12
4). -2 >> 1
5). -2 >>> 1
1). 分析:十六進位制數用0x……來表示,後面一個十六進位制位是四位,兩個十六進位制位為一個位元組,最多後面可以有8個十六進位制位,32個位元組,如:0xFFFFFFFF。 或(“ | ”)運算,全0為0,其他為1。
所以:0xaa 用二進位制表示為 10101010 ,0x55 用二進位制表示為 01010101 ,按位或之後為 11111111 ,十進位制數為255,十六進位制數為 0xFF 。

2). 分析:10進位制轉換成2進位制,用該數字除以2,記錄商和餘數,利用商再次除以2,記錄商和餘數……直到上為0或餘數為0停止,餘數逆序組成二進位制的從低到高位(最後的餘數為二進位制最低位)。與(“ & ”)運算,全1為1,其他為0 。
所以: 15 等於1111 ,240等於 11110000,15前面用0補齊為00001111 ,按位與之後為 00000000 ,即結果為0

3). 分析: 亦或(“ ^ ”)運算,相同取0,不同取1 。
所以:1010 ^ 1100 =0110 , 十進位制表示為6,十六進位制表示為 0x06 。

4). 分析: 帶符號右移(“ >> ”),即有符號位時,負數符號位補1,正數符號位補0, -2 的二進位制求法是正數取反加1,因此 2 的二進位制表示為0000 0000 0000 0000 0000 0000 0000 0010 ,取反加一為
1111 1111 1111 1111 1111 1111 1111 1110 ,即 -2 的二進位制表示。
注: >> , << , >>> , 運算子只針對int型和long型,byte ,short ,char型需要轉換成Int型在進行操作。
所以: 帶符號右移之後為 1111 1111 1111 1111 1111 1111 1111 1111 ,除符號位之外,減一取反,得到帶符號十進 制數為 -1 。

5). 分析:無符號右移 (“ >>> ”) ,即無論正負數,右移之後符號位均補 0 。
所以: -2 的二進位制無符號右移一位之後為 0111 1111 1111 1111 1111 1111 1111 1111,即 2^31 - 1,二的三十一次方減一。
注:右移和無符號右移主要區別就在於左面最高位補 0 還是補 1 的問題,無符號右移任何時候最高位都補 0 , 有符號右移則是正數補 0 ,負數補 1 。(沒有無符號左移!)。

7.&和&&的區別?

&運算子有兩種用法:(1)按位與;(2)邏輯與。&&運算子是短路與運算。邏輯與跟短路與的差別是非常巨大的,雖然二者都要求運算子左右兩端的布林值都是true整個表示式的值才是true。&&之所以稱為短路運算是因為,如果&&左邊的表示式的值是false,右邊的表示式會被直接短路掉,不會進行運算。很多時候我們可能都需要用&&而不是&,例如在驗證使用者登入時判定使用者名稱不是null而且不是空字串,應當寫為:username != null &&!username.equals(“”),二者的順序不能交換,更不能用&運算子,因為第一個條件如果不成立,根本不能進行字串的equals比較,否則會產生NullPointerException異常。注意:邏輯或運算子(|)和短路或運算子(||)的差別也是如此。

8.什麼是值傳遞和引用傳遞?

值傳遞是對基本型變數而言的,傳遞的是該變數的一個副本,改變副本不影響原變數.
引用傳遞一般是對於物件型變數而言的,傳遞的是該物件地址的一個副本, 並不是原物件本身 。
一般認為,java內的傳遞都是值傳遞. java中例項物件的傳遞是引用傳遞 。

9.是否可以在static環境中訪問非static變數?

static變數在Java中是屬於類的,它在所有的例項中的值是一樣的。當類被Java虛擬機器載入的時候,會對static變數進行初始化。如果你的程式碼嘗試不用例項來訪問非static的變數,編譯器會報錯,因為這些變數還沒有被創建出來,還沒有跟任何例項關聯上。

10.Java中的方法覆蓋(Overriding)和方法過載(Overloading)是什麼意思?

Java中的方法過載發生在同一個類裡面兩個或者是多個方法的方法名相同但是引數不同的情況。與此相對,方法覆蓋是說子類重新定義了父類的方法。方法覆蓋必須有相同的方法名,引數列表和返回型別。覆蓋者可能不會限制它所覆蓋的方法的訪問。

11.Java中,什麼是構造方法?什麼是構造方法過載?什麼是複製構造方法?

當新物件被建立的時候,構造方法會被呼叫。每一個類都有構造方法。在程式設計師沒有給類提供構造方法的情況下,Java編譯器會為這個類建立一個預設的構造方法。
Java中構造方法過載和方法過載很相似。可以為一個類建立多個構造方法。每一個構造方法必須有它自己唯一的引數列表。
Java不支援像C++中那樣的複製構造方法,這個不同點是因為如果你不自己寫構造方法的情況下,Java不會建立預設的複製構造方法。

12.Java支援多繼承麼?

Java中類不支援多繼承,只支援單繼承(即一個類只有一個父類)。 但是java中的介面支援多繼承,,即一個子介面可以有多個父介面。(介面的作用是用來擴充套件物件的功能,一個子介面繼承多個父介面,說明子介面擴充套件了多個功能,當類實現介面時,類就擴充套件了相應的功能)。

13.解釋記憶體中的棧(stack)、堆(heap)和方法區(method area)的用法。

通常我們定義一個基本資料型別的變數,一個物件的引用,還有就是函式呼叫的現場儲存都使用JVM中的棧空間;而通過new關鍵字和構造器建立的物件則放在堆空間,堆是垃圾收集器管理的主要區域,由於現在的垃圾收集器都採用分代收集演算法,所以堆空間還可以細分為新生代和老生代,再具體一點可以分為Eden、Survivor(又可分為From Survivor和To Survivor)、Tenured;方法區和堆都是各個執行緒共享的記憶體區域,用於儲存已經被JVM載入的類資訊、常量、靜態變數、JIT編譯器編譯後的程式碼等資料;程式中的字面量(literal)如直接書寫的100、”hello”和常量都是放在常量池中,常量池是方法區的一部分,。棧空間操作起來最快但是棧很小,通常大量的物件都是放在堆空間,棧和堆的大小都可以通過JVM的啟動引數來進行調整,棧空間用光了會引發StackOverflowError,而堆和常量池空間不足則會引發OutOfMemoryError。

14.介面和抽象類的區別是什麼?

從設計層面來說,抽象是對類的抽象,是一種模板設計,介面是行為的抽象,是一種行為的規範。
Java提供和支援建立抽象類和介面。它們的實現有共同點,不同點在於:
介面中所有的方法隱含的都是抽象的。而抽象類則可以同時包含抽象和非抽象的方法。
類可以實現很多個介面,但是隻能繼承一個抽象類
類可以不實現抽象類和介面宣告的所有方法,當然,在這種情況下,類也必須得宣告成是抽象的。
抽象類可以在不提供介面方法實現的情況下實現介面。
Java介面中宣告的變數預設都是final的。抽象類可以包含非final的變數。
Java介面中的成員函式預設是public的。抽象類的成員函式可以是private,protected或者是public。
介面是絕對抽象的,不可以被例項化。抽象類也不可以被例項化,但是,如果它包含main方法的話是可以被呼叫的。
也可以參考JDK8中抽象類和介面的區別。

15.用最有效率的方法計算2乘以8?

答: 2 << 3(左移3位相當於乘以2的3次方,右移3位相當於除以2的3次方)。

16.手寫單例模式(餓漢和飽漢模式)和工廠模式?

(1)單例餓漢模式://餓漢式單例類.在類初始化時,已經自行例項化
2 public class Singleton1 {
3 //私有的預設構造子
4 private Singleton1() {}
5 //已經自行例項化
6 private static final Singleton1 single = new Singleton1();
7 //靜態工廠方法
8 public static Singleton1 getInstance() {
9 return single;
10 }
11 }

(2)懶漢模式://懶漢式單例類.在第一次呼叫的時候例項化
2 public class Singleton2 {
3 //私有的預設構造子
4 private Singleton2() {}
5 //注意,這裡沒有final
6 private static Singleton2 single=null;
7 //靜態工廠方法
8 public synchronized static Singleton2 getInstance() {
9 if (single == null) {
10 single = new Singleton2();
11 }
12 return single;
13 }
14 }

(3)工廠模式:
interface IFactory{
public IProduct createProduct();}
Class Factory implements IFactory{
public IProduct createProduct(){return new Product();}}
Public class client{
Public Static void main (String [] args){IFactory factory=new Factory();
IProduct product=factory.createProduct();
product.ProductMethod();}}

17.String和StringBuilder、StringBuffer的區別?

Java平臺提供了兩種型別的字串:String和StringBuffer/StringBuilder,它們可以儲存和操作字串。其中String是隻讀字串,也就意味著String引用的字串內容是不能被改變的。而StringBuffer/StringBuilder類表示的字串物件可以直接進行修改。StringBuilder是Java 5中引入的,它和StringBuffer的方法完全相同,區別在於它是在單執行緒環境下使用的,因為它的所有方面都沒有被synchronized修飾,因此它的效率也比StringBuffer要高。

二、JAVA基礎篇-集合與陣列

18.Java集合框架是什麼?說出一些集合框架的優點

每種程式語言中都有集合,最初的Java版本包含幾種集合類:Vector、Stack、HashTable和Array。隨著集合的廣泛使用,Java1.2提出了囊括所有集合介面、實現和演算法的集合框架。在保證執行緒安全的情況下使用泛型和併發集合類,Java已經經歷了很久。它還包括在Java併發包中,阻塞介面以及它們的實現。集合框架的部分優點如下:
(1)使用核心集合類降低開發成本,而非實現我們自己的集合類。
(2)隨著使用經過嚴格測試的集合框架類,程式碼質量會得到提高。
(3)通過使用JDK附帶的集合類,可以降低程式碼維護成本。
(4)複用性和可操作性。

19.集合框架中的泛型有什麼優點?

Java1.5引入了泛型,所有的集合介面和實現都大量地使用它。泛型允許我們為集合提供一個可以容納的物件型別,因此,如果你新增其它型別的任何元素,它會在編譯時報錯。這避免了在執行時出現ClassCastException,因為你將會在編譯時得到報錯資訊。泛型也使得程式碼整潔,我們不需要使用顯式轉換和instanceOf操作符。它也給執行時帶來好處,因為不會產生型別檢查的位元組碼指令。

20.Java集合框架的基礎介面有哪些?

Collection為集合層級的根介面。一個集合代表一組物件,這些物件即為它的元素。Java平臺不提供這個介面任何直接的實現。## 標題 ##
Set是一個不能包含重複元素的集合。這個介面對數學集合抽象進行建模,被用來代表集合,就如一副牌。
List是一個有序集合,可以包含重複元素。你可以通過它的索引來訪問任何元素。List更像長度動態變換的陣列。
Map是一個將key對映到value的物件.一個Map不能包含重複的key:每個key最多隻能對映一個value。
一些其它的介面有Queue、Dequeue、SortedSet、SortedMap和ListIterator。

21.為何Collection不從Cloneable和Serializable介面繼承

Collection介面指定一組物件,物件即為它的元素。如何維護這些元素由Collection的具體實現決定。例如,一些如List的Collection實現允許重複的元素,而其它的如Set就不允許。很多Collection實現有一個公有的clone方法。然而,把它放到集合的所有實現中也是沒有意義的。這是因為Collection是一個抽象表現。重要的是實現。
當與具體實現打交道的時候,克隆或序列化的語義和含義才發揮作用。所以,具體實現應該決定如何對它進行克隆或序列化,或它是否可以被克隆或序列化。
在所有的實現中授權克隆和序列化,最終導致更少的靈活性和更多的限制。特定的實現應該決定它是否可以被克隆和序列化。

22.為何Map介面不繼承Collection介面?

儘管Map介面和它的實現也是集合框架的一部分,但Map不是集合,集合也不是Map。因此,Map繼承Collection毫無意義,反之亦然。
如果Map繼承Collection介面,那麼元素去哪兒?Map包含key-value對,它提供抽取key或value列表集合的方法,但是它不適合“一組物件”規範。

23.什麼是迭代器(Iterator)?

Iterator介面提供了很多對集合元素進行迭代的方法。每一個集合類都包含了可以返回迭代器例項的迭代方法。迭代器可以在迭代的過程中刪除底層集合的元素,但是不可以直接呼叫集合的remove(Object Obj)刪除,可以通過迭代器的remove()方法刪除。

24.Iterator和ListIterator的區別是什麼?

下面列出了他們的區別:
Iterator可用來遍歷Set和List集合,但是ListIterator只能用來遍歷List。
Iterator對集合只能是前向遍歷,ListIterator既可以前向也可以後向。
ListIterator實現了Iterator介面,幷包含其他的功能,比如:增加元素,替換元素,獲取前一個和後一個元素的索引,等等。

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

快速失敗:當你在迭代一個集合的時候,如果有另一個執行緒正在修改你正在訪問的那個集合時,就會丟擲一個ConcurrentModification異常。
在java.util包下的都是快速失敗。
安全失敗:你在迭代的時候會去底層集合做一個拷貝,所以你在修改上層集合的時候是不會受影響的,不會丟擲ConcurrentModification異常。
在java.util.concurrent包下的全是安全失敗的。

26.Java中的HashMap的工作原理是什麼?

我們知道在Java中最常用的兩種結構是陣列和模擬指標(引用),幾乎所有的資料結構都可以利用這兩種來組合實現,HashMap也是如此。實際上HashMap是一個“連結串列雜湊”,如下是它資料結構:最左側是一個數組,陣列中的每一個元素都是一個連結串列,連結串列的每一個元素都是entry。

HashMap是基於hashing的原理,我們使用put(key, value)儲存物件到HashMap中,使用get(key)從HashMap中獲取物件。當我們給put()方法傳遞鍵和值時,我們先對鍵呼叫hashCode()方法,返回的hashCode用於找到bucket位置來儲存Entry物件。

27.當兩個物件的hashcode相同會發生什麼?

因為hashcode相同,所以它們的bucket位置相同,‘碰撞’會發生。因為HashMap使用連結串列儲存物件,這個Entry(包含有鍵值對的Map.Entry物件)會儲存在連結串列中。

28.如果兩個鍵的hashcode相同,你如何獲取值物件?

當我們呼叫get()方法,HashMap會使用鍵物件的hashcode找到bucket位置,然後會呼叫keys.equals()方法去找到連結串列中正確的節點,最終找到要找的值物件。

29.hashCode()和equals()方法有何重要性?

HashMap使用Key物件的hashCode()和equals()方法去決定key-value對的索引。當我們試著從HashMap中獲取值的時候,這些方法也會被用到。如果這些方法沒有被正確地實現,在這種情況下,兩個不同Key也許會產生相同的hashCode()和equals()輸出,HashMap將會認為它們是相同的,然後覆蓋它們,而非把它們儲存到不同的地方。同樣的,所有不允許儲存重複資料的集合類都使用hashCode()和equals()去查詢重複,所以正確實現它們非常重要。equals()和hashCode()的實現應該遵循以下規則:
(1)如果o1.equals(o2),那麼o1.hashCode() == o2.hashCode()總是為true的。
(2)如果o1.hashCode() == o2.hashCode(),並不意味著o1.equals(o2)會為true。
具體可以參考 http://blog.csdn.net/javazejian/article/details/51348320

30.HashMap和Hashtable有什麼區別?

1、HashMap是非執行緒安全的,HashTable是執行緒安全的。
2、HashMap的鍵和值都允許有null值存在,而HashTable則不行。
3、因為執行緒安全的問題,HashMap效率比HashTable的要高。
4、Hashtable是同步的,而HashMap不是。因此,HashMap更適合於單執行緒環境,而Hashtable適合於多執行緒環境。
一般現在不建議用HashTable, ①是HashTable是遺留類,內部實現很多沒優化和冗餘。②即使在多執行緒環境下,現在也有同步的ConcurrentHashMap替代,沒有必要因為是多執行緒而用HashTable。

31.如何決定選用HashMap還是TreeMap?

對於在Map中插入、刪除和定位元素這類操作,HashMap是最好的選擇。然而,假如你需要對一個有序的key集合進行遍歷,TreeMap是更好的選擇。基於你的collection的大小,也許向HashMap中新增元素會更快,將map換為TreeMap進行有序key的遍歷。

32.ArrayList和Vector有何異同點?

ArrayList和Vector在很多時候都很類似。
(1)兩者都是基於索引的,內部由一個數組支援。
(2)兩者維護插入的順序,我們可以根據插入順序來獲取元素。
(3)ArrayList和Vector的迭代器實現都是fail-fast的。
(4)ArrayList和Vector兩者允許null值,也可以使用索引值對元素進行隨機訪問。
以下是ArrayList和Vector的不同點。
(1)Vector是同步的,而ArrayList不是。然而,如果你尋求在迭代的時候對列表進行改變,你應該使用CopyOnWriteArrayList。
(2)ArrayList比Vector快,它因為有同步,不會過載。
(3)ArrayList更加通用,因為我們可以使用Collections工具類輕易地獲取同步列表和只讀列表。

33.Array和ArrayList有何區別?什麼時候更適合用Array?

Array可以容納基本型別和物件,而ArrayList只能容納物件。
Array是指定大小的,而ArrayList大小是固定的。
Array沒有提供ArrayList那麼多功能,比如addAll、removeAll和iterator等。儘管ArrayList明顯是更好的選擇,但也有些時候Array比較好用。
(1)如果列表的大小已經指定,大部分情況下是儲存和遍歷它們。
(2)對於遍歷基本資料型別,儘管Collections使用自動裝箱來減輕編碼任務,在指定大小的基本型別的列表上工作也會變得很慢。
(3)如果你要使用多維陣列,使用[][]比List