天天看點

Java面試題目彙總之一

一、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 {

4 private Singleton2() {}

5 //注意,這裡沒有final

6 private static Singleton2 single=null;

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)如果你要使用多元數組,使用[][]。

原文釋出時間為:2018-11-7

本文來自雲栖社群合作夥伴“

Java程式員聯盟

”,了解相關資訊可以關注“

”。