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)單例餓漢模式://餓漢式單例類.在類初始化時,已經自行實例化

public class Singleton1 {
 //私有的默認構造子
private Singleton1() {}
 //已經自行實例化
private static final Singleton1 single = new Singleton1();
 //靜態工廠方法
public static Singleton1 getInstance() {
         return single;
     }
 }

(2)懶漢模式://懶漢式單例類.在第一次調用的時候實例化

 public class Singleton2 {
 //私有的默認構造子
 private Singleton2() {}
 //注意,這裏沒有final
 private static Singleton2 single=null;
 //靜態工廠方法
 public synchronized static Singleton2 getInstance() {
       if (single == null) {
             single = new Singleton2();
       }
       return single;
       }
 }

(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

作者:hopeplus  
原文:https://blog.csdn.net/hope900/article/details/78647466 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章