Java常見面試題總結

轉載請註明出處https://www.cnblogs.com/lwy521/java


1.面向對象c++

面向對象是基於現實事物,將事物抽象成對象,賦予對象屬性和方法,讓後讓每一對象去執行本身的方法與屬性,面向對象有三大基本特性:程序員

封裝:把對象的屬性方法結合在一塊兒,成爲一個獨立的代碼塊。並儘量隱藏對象的內部實現環節面試

繼承:從已有的類派生新的類。新類能獲得已有的類的屬性和方法,並能夠擴展出新的屬性和行爲,繼承的做用是爲了提升代碼的複用性,繼承具備傳遞性,單一性正則表達式

多態:是同一種行爲,有多重不一樣的表現狀態或形態的能力,分爲行爲的多態和對象的多態,表現形式有重寫重載向上造型算法

2.重載重寫的區別數據庫

1>重寫:發生在父子類中,方法名相同,參數列表相同,方法體不一樣,遵循運行期綁定,看對象類型類調用方法編程

兩同兩小一大設計模式

兩小:返回值,異常小於等於父類返回值,異常數組

一大:訪問修飾符大於等於父類訪問修飾符

2>重載:發生在一個類中,方法名相同,參數列表不一樣,方法體不用,遵循"編譯期綁定",看引用/參數類型來綁定方法. 

爲何不能根據返回類型來區分重載",快說出你的答案吧!

由於調用時不能指定類型信息,編譯器不知道你要調用哪一個函數。 例如:

float max(int a, int b);

int max(int a, int b);

當調用max(1, 2);時沒法肯定調用的是哪一個,單從這一點上來講,僅返回值類型不一樣的重載是不該該容許的。

3.抽象類與接口的區別

1>接口是徹底抽象的,不存在方法的實現

    抽象類能夠方法的實現

2>接口使用implement實現方法,子類必須實現方法

    抽象類經過extends繼承,若是子類不是抽象類,那麼必須去實現抽象方法

3>接口沒有構造器

    抽象類有構造器,但不能被實例化

4>抽象方法能夠有public、protected和default這些修飾符

           接口只能被默認的public修飾

5>抽象方法能夠有main方法而且咱們能夠運行它;

         接口沒有

6>抽象方法能夠繼承一個類和實現多個接口

           接口只能夠繼承一個或多個其餘接口

聲明方法的存在而不去實現它的類被叫作抽象類(abstract class),它用於要建立一個體現某些基本行爲的類,併爲該類聲明方法,但不能在該類中實現該類的狀況。不能建立abstract 類的實例。然而能夠建立一個變量,其類型是一個抽象類,並讓它指向具體子類的一個實例。不能有抽象構造函數或抽象靜態方法。Abstract 類的子類爲它們父類中的全部抽象方法提供實現,不然它們也是抽象類爲。取而代之,在子類中實現該方法。知道其行爲的其它類能夠在類中實現這些方法。

  接口(interface)是抽象類的變體。在接口中,全部方法都是抽象的。多繼承性可經過實現這樣的接口而得到。接口中的全部方法都是抽象的,沒有一個有程序體。接口只能夠定義static final成員變量。接口的實現與子類類似,除了該實現類不能從接口定義中繼承行爲。當類實現特殊接口時,它定義(即將程序體給予)全部這種接口的方法。而後,它能夠在實現了該接口的類的任何對象上調用接口的方法。因爲有抽象類,它容許使用接口名做爲引用變量的類型。一般的動態聯編將生效。引用能夠轉換到接口類型或從接口類型轉換,instanceof 運算符能夠用來決定某對象的類是否實現了接口。

4.什麼是匿名內部類

沒有名字的類稱爲匿名內部類,想要建立一個父類接口的子類對象,且該對象只被建立一次,此時                   該類沒必要命名,稱爲匿名內部類

1.只能用於繼承一個類或者實現一個接口,而且只能建立一個該類的實例

2.匿名內部類中沒有構造方法,訪問控制修飾符.也不能有靜態的變量,方法和類.

3.匿名內部類屬於局部內部類,因此局部內部類的限制也對其有效,只能訪問外部類的靜態方法和靜態變量

5.int 與integer的區別

1>int是基本數據對象,不能直接參與面向對象的開發,因此提供了包裝類Integer

2>integer變量必須實例化後才能使用,int變量不須要.  

3>Integer的默認值爲null,int的默認值爲0;

4>jdk1.5提供自動拆裝箱,知足了基本數據變量與引用類型的賦值

6.正則表達式

正則表達式是用於字符串的匹配和替換,驗證當前字符串是否知足各類需求.                                                      

7.String,StringBuilder和StringBuffer的區別。

       1.String:字符串常量,是不可變對象,每次對String類型進行改變都等同於生成了一個新的String對象,速度慢. 適用於少許字符串操做的狀況.

       2.StringBuffer:其中不少方法有synchronized關鍵字,是線程安全的可變字符序列,速度較快.適用於多線程下在字符緩衝區進行大量操做的狀況

       2.StringBuilder,JDK1.5以後推出的與StringBuffer兼容的API,用做StringBuffer的一個簡單替換,單個線程使用時,建議優先採用,速度最快.適用於多線程下載字符緩衝區進行大量操做的狀況.

 

8.什麼是socket?

套接字(socket)是一個網絡中特定節點的網絡標識符,套接字包含一個特定的地址和端口號,java中的網絡通訊是經過socket實現的,socket包含兩大類: serversocket和socket兩大類,ServerSocket用於服務器端,能夠經過accept方法監聽請求,監聽請求後返回Socket,Socket用於完成具體數據傳輸,客戶端也可使用Socket發起請求並傳輸數據.

9.Html與xml的區別。

       1.HTML:超文本標記語言,XML:可擴展標記語言

       2.HTML語法不嚴格區分大小寫,能夠自動過濾空格,能夠不適用引號等,XML卻相反

       3.HTML中有固定的標籤,xml能夠自定義和擴展標籤

       4.HTML是用來顯示數據的,xml是用來描述,存放數據的.

10.Throw與throws的區別

1.Throws出如今方法函數頭;而throw出如今函數體

2.throws表示出現異常的一種可能性,並不必定會發生這些異常;

   throw則是拋出了異常,執行throw則必定拋出了某種異常對象.

3.它們都是消極處理異常的方式,只是拋出或者可能拋出異常,可是不會由函數去處理異常,真正的處理異常由函數的上層調用處理.

11.說一說你對異常處理機制的理解

若是程序不能正常的運行,那麼能夠就能夠經過另外一種路徑退出方法,在這種狀況下會拋出一個封裝了錯誤信息的對象。這個方法會馬上退出同時不返回任何值。另外,調用這個方法的其餘代碼也沒法繼續執行,異常處理機制會將代碼執行交給異常處理器。

若是出現RuntimeException,那麼必定是程序員的錯誤

遇到問題不進行具體處理,而是繼續拋給調用者 拋出異常有三種形式,

       1.是throw,一個throws,還有一種系統自動拋異常。

       2.針對性處理方式:使用try-catch捕獲異常

12.   Final和finally以及finalize的區別

       1.Final:修飾符關鍵字,用於聲明屬性,方法和類,分別表示:屬性不可改變,方法不能被重寫,類不能被繼承.

       2.Finally:是異常處理機制的一部分,finally確保只要程序執行到try塊中,那麼finally塊中的代碼一定執行.

       3.Finalize:是Object類的一個方法,在垃圾收集器(gc)將對象從內存中清除出去以前,作必要的清理工做和其餘資源的回收.

 

13.List,set,map的區別。

       1.List是Collection的一個子接口,稱爲線性表,是可重複有序集,能夠經過下標對元素操做,經常使用實現類有ArrayList:數組實現,查詢性能好.和LinkedList:鏈表實現,便於增刪元素.

       2.set也是Collection的一個子接口,是不可重複且無序集,但其實現類能對集合中的對象按照特定的方式排序,好比TreeSet.經常使用實現類有HashSet和TreeSet.

       3.Map接口,查找表,其中的每個元素是一個鍵值對,鍵對象不可重複,值對象可重複.經常使用實現類有:HashMap:當今世界查詢速度最快的數據結構.HashTable 和LinkedHashMap 等.

Set裏的元素是不能重複的,那麼用什麼方法來區分重複與否呢? 是用==仍是equals()? 它們有何區別:

 

Set裏的元素是不能重複的,那麼用iterator()方法來區分重複與否。equals()是判讀兩個Set是否相等。

equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋,爲的是當兩個分離的對象的內容和類型相配的話,返回真值。

 

14.HashMap與HashTable的區別。

       1.HashMap是線程不安全的,HashMap是Map的一個子接口,是將鍵映射到值獲得對象,不容許鍵值重複,容許空鍵和空值.

       2.HashTable是線程安全的集合,不容許null值做爲key或value,它是synchronized修飾的,多個線程訪問時不須要本身爲它的方法實現同步,而HashMap在被多個線程訪問時須要本身爲它的方法實現同步.

3.因爲HashMap非線程安全,因此HashMap的效率要比HashTable的效率高一些.

15.線程與進程的區別

一、定義

進程:是執行中一段程序,即一旦程序被載入到內存中並準備執行,它就是一個進程。進程是操做系統資源分配的基本單位.

線程:單個進程中執行中每一個任務就是一個線程。

線程:是進程中任務調度和執行的基本單位

       二、一個線程只能屬於一個進程,可是一個進程能夠擁有多個線程。多線程處理就是容許一個進程中在同一時刻執行多個任務。

       三、線程是一種輕量級的進程,與進程相比,線程給操做系統帶來側建立、維護、和管理的負擔要輕,意味着線程的代價或開銷比較小。

       4.沒有線程的進程能夠看作是單線程的,若是一個進程內有多個線程,則執行過程不是一條線的,而是多條線(線程)共同完成的;線程是進程的一部分,因此線程也被稱爲輕權進程或者輕量級進程。

16.線程的生命週期?線程有哪些狀態

       一、線程的生命週期:新建(New)、就緒(Runnable)、運行(Running)、阻塞(Blocked)和死亡(Dead)5種狀態。

17.說一說你對反射機制的見解?反射機制的優缺點?

       1.反射機制:將在編譯期實例化一個類,操做其屬性和方法的操做轉換爲運行期決定.

       2.適度使用能夠提升代碼的靈活度,過分使用會下降代碼運行效率,增長資源開銷.

       3.步驟:

              1.經過class類中的forName靜態方法獲取加載類對象

              2.經過類對象實例化該類.newInstance方法

              3.獲取類中的方法,經過傳入參數匹配對應的方法

              getDeclaredMethods("方法名","數據類型.class")

              4.傳入實參,執行該方法

              invoke(obj,"實參").

18.如何建立一個線程池?利用線程池有哪些好處。(數據庫鏈接池)

1.線程池:管理線程機制,主要解決重用線程和控制線程數量.

2.能夠有效處理多個線程的併發問題,避免大量的線程由於互相強佔系統資源致使阻塞現象,有效下降頻繁建立和銷燬對性能帶來的開銷.

3.對線程數量的控制也應在硬件的承受範圍以內.

4.建立:fixedThreadPool:正規線程池,指定了線程數,有核心線程,正規的併發線程,響應速度快,多用於服務器.

ExecutorService threadpool = Executors.newFixedThreadPool(3);

19.HTTP協議

HttP協議:超文本傳輸協議

1.該協議是應用層協議,該協議應用在瀏覽器與服務器之間

2.規定了瀏覽器與服務器之間數據傳輸的方式,以及數據內容定義等規則

3.HTTP協議要求必須創建在可靠的傳輸協議基礎上,一般使用的是TCP協議.

4.HTTP協議定義了瀏覽器(瀏覽器)與服務器之間的交互規則:要求客戶端發起請求,服務端接收請   求並處理,而後響應客戶端.不容許服務端主動響應客戶端.

5.HTTP協議要求使用的字符集爲ISO8859-1,不支持中文字符,因此傳輸中文時須要特別處理.

 

19.靜態變量和實例變量的區別

1.實例變量是屬於某個對象的屬性,必須建立了實例對象,其中的實例變量纔會被分配空間,才能使用這個實例變量.

2.靜態變量屬於類,也稱類變量,只要程序加載了類的字節碼文件,無需建立任何實例對象,靜態變量就會被分配空間(方法區),就能夠被使用

3.總結:實例變量必須在建立對象後才能夠經過這個對象來使用,而靜態變量能夠直接使用類名類引用.

 

20.內存管理:

       1.堆中存放: new出來的對象(包括實例變量)

              實例變量生命週期:從對象被建立到被回收

       2.棧中存放: 正在調用的方法中的局部變量(包括方法中的參數)

              局部變量生命週期:調用方法時存在棧中,方法結束時與棧幀一次消失.

       3.方法區: 存儲.class字節碼文件(包括方法,靜態變量);

 

21.&和&&的區別:

&是位運算符。&&是布爾邏輯運算符。

 

22.Collection 和 Collections的區別:

 

Collections是個java.util下的類,它包含有各類有關集合操做的靜態方法。

Collection是個java.util下的接口,它是各類集合結構的父接口。

22.GC是什麼? 爲何要有GC? (基礎):

 

 

GC是垃圾收集器。Java 程序員不用擔憂內存管理,由於垃圾收集器會自動進行管理。要請求垃圾收集,能夠調用下面的方法之一:

System.gc()

Runtime.getRuntime().gc()。

 

23.String s = new String("xyz");建立了幾個String Object:

 

兩個對象,一個是「xyx」,一個是指向「xyx」的引用對象s。

第一個對象是字符串常量"xyz" 第二個對象是new String("xyz")的時候產生的,在堆中分配內存給這個對象,只不過這個對象的內容是指向字符串常量"xyz" 另外還有一個引用s,指向第二個對象。這是一個變量,在棧中分配內存。

24.sleep() 和 wait() 有什麼區別:

sleep()方法是使線程中止一段時間的方法。在sleep 時間間隔期滿後,線程不必定當即恢復執行。這是由於在那個時刻,其它線程可能正在運行並且沒有被調度爲放棄執行,除非(a)「醒來」的線程具備更高的優先級(b)正在運行的線程由於其它緣由而阻塞。

wait()是線程交互時,若是線程對一個同步對象x 發出一個wait()調用,該線程會暫停執行,被調對象進入等待狀態,直到被喚醒或等待時間到。

 

25.數組有沒有length()這個方法? String有沒有length()這個方法:

數組沒有length()這個方法,有length的屬性。

String有有length()這個方法。

 

26.啓動一個線程是用run()仍是start():

 

 

啓動一個線程是調用start()方法,使線程所表明的虛擬處理機處於可運行狀態,這意味着它能夠由JVM調度並執行。這並不意味着線程就會當即運行。run()方法能夠產生必須退出的標誌來中止一個線程。

 

27.構造器Constructor是否可被override:

構造器Constructor不能被繼承,所以不能重寫Overriding,但能夠被重載Overloading。

 

 

28.try {}裏有一個return語句,那麼緊跟在這個try後的finally {}裏的code會不會被執行,何時被執行,在return前仍是後:

會執行,在return前執行。

在finally中改變返回值的作法是很差的,由於若是存在finally代碼塊,try中的return語句不會立馬返回調用者,而是記錄下返回值待finally代碼塊執行完畢以後再向調用者返回其值,而後若是在finally中修改了返回值,就會返回修改後的值。顯然,在finally中返回或者修改返回值會對程序形成很大的困擾,C#中直接用編譯錯誤的方式來阻止程序員幹這種齷齪的事情,Java中也能夠經過提高編譯器的語法檢查級別來產生警告或錯誤,Eclipse中能夠在如圖所示的地方進行設置,強烈建議將此項設置爲編譯錯誤。

 

29.ArrayList和Vector的區別,HashMap和Hashtable的區別:

 

答:就ArrayList與Vector主要從二方面來講.

 

一.同步性:Vector是線程安全的,也就是說是同步的,而ArrayList是線程序不安全的,不是同步的

 

二.數據增加:當須要增加時,Vector默認增加爲原來一培,而ArrayList倒是原來的一半

 

就HashMap與HashTable主要從三方面來講。

 

一.歷史緣由:Hashtable是基於陳舊的Dictionary類的,HashMap是Java 1.2引進的Map接口的一個實現

 

二.同步性:Hashtable是線程安全的,也就是說是同步的,而HashMap是線程序不安全的,不是同步的

 

三.值:只有HashMap可讓你將空值做爲一個表的條目的key或value。

30.說一說Servlet的生命週期:

 

答:servlet有良好的生存期的定義,包括加載和實例化、初始化、處理請求以及服務結束。這個生存期由javax.servlet.Servlet接口的init,service和destroy方法表達。

 

31.JAVA SERVLET API中forward() 與redirect()的區別:

答:前者僅是容器中控制權的轉向,在客戶端瀏覽器地址欄中不會顯示出轉向後的地址;後者則是徹底的跳轉,瀏覽器將會獲得跳轉的地址,並從新發送請求連接。這樣,從瀏覽器的地址欄中能夠看到跳轉後的連接地址。因此,前者更加高效,在前者能夠知足須要時,儘可能使用forward()方法,而且,這樣也有助於隱藏實際的連接。在有些狀況下,好比,須要跳轉到一個其它服務器上的資源,則必須使用sendRedirect()方法。

 

32.Class.forName的做用?爲何要用:

答:調用該訪問返回一個以字符串指定類名的類的對象。

 

33.Jdo是什麼:

JDO是Java對象持久化的新的規範

34.xml有哪些解析技術?區別是什麼:

答:有DOM,SAX,STAX等

DOM:處理大型文件時其性能降低的很是厲害。這個問題是由DOM的樹結構所形成的,這種結構佔用的內存較多,並且DOM必須在解析文件以前把整個文檔裝入內存,適合對XML的隨機訪問

SAX:不現於DOM,SAX是事件驅動型的XML解析方式。它順序讀取XML文件,不須要一次所有裝載整個文件。當遇到像文件開頭,文檔結束,或者標籤開頭與標籤結束時,它會觸發一個事件,用戶經過在其回調事件中寫入處理代碼來處理XML文件,適合對XML的順序訪問

 

STAX:Streaming API for XML (StAX)。

35.基本數據類型包括byte一、short二、int四、long八、char二、float四、double八、boolean1

36.序列化和反序列化的概念

  把對象轉換爲字節序列的過程稱爲對象的序列化

  把字節序列恢復爲對象的過程稱爲對象的反序列化

 

37.heap和stack有什麼區別:

棧是一種線形集合,其添加和刪除元素的操做應在同一段完成。棧按照後進先出的方式進行處理。堆是棧的一個組成元素。

38.J2EE是技術仍是平臺仍是框架:

J2EE自己是一個標準,一個爲企業分佈式應用的開發提供的標準平臺。

J2EE也是一個框架,包括JDBC、JNDI、RMI、JMS、EJB、JTA等技術。

編寫 java文件的注意事項:

39.經常使用的設計模式?說明工廠模式:

Java中的23種設計模式:Factory(工廠模式),Builder(建造模式), Factory Method(工廠方法模式),Prototype(原始模型模式),Singleton(單例模式), Facade(門面模式),Adapter(適配器模式), Bridge(橋樑模式), Composite(合成模式),Decorator(裝飾模式), Flyweight(享元模式), Proxy(代理模式),Command(命令模式), Interpreter(解釋器模式), Visitor(訪問者模式),Iterator(迭代子模式), Mediator(調停者模式), Memento(備忘錄模式),Observer(觀察者模式),State(狀態模式),Strategy(策略模式),Template Method(模板方法模式), Chain Of Responsibleity(責任鏈模式)。

工廠模式:工廠模式是一種常常被使用到的模式,根據工廠模式實現的類能夠根據提供的數據生成一組類中某一個類的實例,一般這一組類有一個公共的抽象父類而且實現了相同的方法,可是這些方法針對不一樣的數據進行了不一樣的操做。首先須要定義一個基類,該類的子類經過不一樣的方法實現了基類中的方法。而後須要定義一個工廠類,工廠類能夠根據條件生成不一樣的子類實例。當獲得子類的實例後,開發人員能夠調用基類中的方法而沒必要考慮到底返回的是哪個子類的實例。

40.java中有幾種方法能夠實現一個線程?

有兩種實現方法,分別是繼承Thread類與實現Runnable接口

41.什麼是java序列化,如何實現java序列化:

序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。能夠對流化後的對象進行讀寫操做,也可將流化後的對象傳輸於網絡之間。序列化是爲了解決在對對象流進行讀寫操做時所引起的問題。序列化的實現:將須要被序列化的類實現Serializable接口,該接口沒有須要實現的方法,implements Serializable只是爲了標註該對象是可被序列化的,而後使用一個輸出流(如:FileOutputStream)來構造一個ObjectOutputStream(對象流)對象,接着,使用ObjectOutputStream對象的writeObject(Object obj)方法就能夠將參數爲obj的對象寫出(即保存其狀態),要恢復的話則用輸入流。

 

42.垃圾回收的優勢和原理。並考慮2種回收機制

答:Java語言中一個顯著的特色就是引入了垃圾回收機制,使c++程序員最頭疼的內存管理的問題迎刃而解,它使得Java程序員在編寫程序的時候再也不須要考慮內存管理。因爲有個垃圾回收機制,Java中的對象再也不有"做用域"的概念,只有對象的引用纔有"做用域"。垃圾回收能夠有效的防止內存泄露,有效的使用可使用的內存。垃圾回收器一般是做爲一個單獨的低級別的線程運行,不可預知的狀況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清楚和回收,程序員不能實時的調用垃圾回收器對某個對象或全部對象進行垃圾回收。回收機制有分代複製垃圾回收和標記垃圾回收,增量垃圾回收。

 

43.是否能夠繼承String類

答:String類是final類故不能夠繼承

 

 

44.抽象類的特色:

1:抽象方法只能定義在抽象類中,抽象類和抽象方法必須由abstract關鍵字修飾(能夠描述類和方法,不能夠描述變量)。

2:抽象方法只定義方法聲明,並不定義方法實現。

3:抽象類不能夠被建立對象(實例化)。

4:只有經過子類繼承抽象類並覆蓋了抽象類中的全部抽象方法後,該子類才能夠實例化。不然,該子類仍是一個抽象類。

5: 抽象類只能單繼承。

 

 

 

45.js塊元素,行元素

塊元素

<address> 定義地址

<caption> 定義表格標題

<dd> 定義列表中定義條目

<div> 定義文檔中的分區或節

<dl> 定義列表

<dt> 定義列表中的項目

<fieldset> 定義一個框架集

<form> 建立 HTML 表單

<h1> 定義最大的標題

<h2> 定義副標題

<h3> 定義標題

<h4> 定義標題

<h5> 定義標題

<h6> 定義最小的標題

<hr> 建立一條水平線

<legend> 元素爲 fieldset 元素定義標題

<li> 標籤訂義列表項目

<noframes> 爲那些不支持框架的瀏覽器顯示文本,於 frameset 元素內部

<noscript> 定義在腳本未被執行時的替代內容

<ol> 定義有序列表

<ul> 定義無序列表

<p> 標籤訂義段落

<pre> 定義預格式化的文本

<table> 標籤訂義 HTML 表格

<tbody> 標籤表格主體(正文)

<td> 表格中的標準單元格

<tfoot> 定義表格的頁腳(腳註或表注)

<th> 定義表頭單元格

<thead> 標籤訂義表格的表頭

<tr> 定義表格中的行

<a>行元素 標籤可定義錨

<abbr> 表示一個縮寫形式

<acronym> 定義只取首字母縮寫

<b> 字體加粗

<bdo> 可覆蓋默認的文本方向

<big> 大號字體加粗

<br> 換行

<cite> 引用進行定義

<code> 定義計算機代碼文本

<dfn> 定義一個定義項目

<em> 定義爲強調的內容

<i> 斜體文本效果

<img> 向網頁中嵌入一幅圖像

<input> 輸入框

<kbd> 定義鍵盤文本

<label> 標籤爲 input 元素定義標註(標記)

<q> 定義短的引用

<samp> 定義樣本文本

<select> 建立單選或多選菜單

<small> 呈現小號字體效果

<span> 組合文檔中的行內元素

<strong> 語氣更強的強調的內容

<sub> 定義下標文本

<sup> 定義上標文本

<textarea> 多行的文本輸入控件

<tt> 打字機或者等寬的文本效果

<var> 定義變量

 

46.修飾權限問題

 

 

47.描述一下JVM加載class文件的原理機制?

答:JVM中類的裝載是由類加載器(ClassLoader)和它的子類來實現的,Java中的類加載器是一個重要的Java運行時系統組件,它負責在運行時查找和裝入類文件中的類。 因爲Java的跨平臺性,通過編譯的Java源程序並非一個可執行程序,而是一個或多個類文件。當Java程序須要使用某個類時,JVM會確保這個類已經被加載、鏈接(驗證、準備和解析)和初始化。類的加載是指把類的.class文件中的數據讀入到內存中,一般是建立一個字節數組讀入.class文件,而後產生與所加載類對應的Class對象。加載完成後,Class對象還不完整,因此此時的類還不可用。當類被加載後就進入鏈接階段,這一階段包括驗證、準備(爲靜態變量分配內存並設置默認的初始值)和解析(將符號引用替換爲直接引用)三個步驟。最後JVM對類進行初始化,包括:1)若是類存在直接的父類而且這個類尚未被初始化,那麼就先初始化父類;2)若是類中存在初始化語句,就依次執行這些初始化語句。 類的加載是由類加載器完成的,類加載器包括:根加載器(BootStrap)、擴展加載器(Extension)、系統加載器(System)和用戶自定義類加載器(java.lang.ClassLoader的子類)。從Java 2(JDK 1.2)開始,類加載過程採起了父親委託機制(PDM)。PDM更好的保證了Java平臺的安全性,在該機制中,JVM自帶的Bootstrap是根加載器,其餘的加載器都有且僅有一個父類加載器。類的加載首先請求父類加載器加載,父類加載器無能爲力時才由其子類加載器自行加載。JVM不會向Java程序提供對Bootstrap的引用。下面是關於幾個類加載器的說明:

Bootstrap:通常用本地代碼實現,負責加載JVM基礎核心類庫(rt.jar);

Extension:從java.ext.dirs系統屬性所指定的目錄中加載類庫,它的父加載器是Bootstrap;

System:又叫應用類加載器,其父類是Extension。它是應用最普遍的類加載器。它從環境變量classpath或者系統屬性java.class.path所指定的目錄中加載類,是用戶自定義加載器的默認父加載器。

48.靜態嵌套類(Static Nested Class)和內部類(Inner Class)的不一樣?

答:Static Nested Class是被聲明爲靜態(static)的內部類,它能夠不依賴於外部類實例被實例化。而一般的內部類須要在外部類實例化後才能實例化,其語法看起來挺詭異的,以下所示。

 

面試題 - 下面的代碼哪些地方會產生編譯錯誤?

class Outer {

 

    class Inner {}

 

    public static void foo() { new Inner(); }

 

    public void bar() { new Inner(); }

 

    public static void main(String[] args) {

        new Inner();

    }

}

注意:Java中非靜態內部類對象的建立要依賴其外部類對象,上面的面試題中foo和main方法都是靜態方法,靜態方法中沒有this,也就是說沒有所謂的外部類對象,所以沒法建立內部類對象,若是要在靜態方法中建立內部類對象,能夠這樣作:

new Outer().new Inner();

 

49.數據類型之間的轉換:

如何將字符串轉換爲基本數據類型?

如何將基本數據類型轉換爲字符串?

答:

調用基本數據類型對應的包裝類中的方法parseXXX(String)或valueOf(String)便可返回相應基本類型;

一種方法是將基本數據類型與空字符串("")鏈接(+)便可得到其所對應的字符串;另外一種方法是調用String 類中的valueOf()方法返回相應字符串

50.如何實現字符串的反轉及替換?

答:方法不少,能夠本身寫實現也可使用String或StringBuffer/StringBuilder中的方法。有一道很常見的面試題是用遞歸實現字符串反轉,代碼以下所示:

public static String reverse(String originStr) {

       if(originStr == null || originStr.length() <= 1)

              return originStr;

       return reverse(originStr.substring(1)) + originStr.charAt(0);

}

 

51.Error和Exception有什麼區別?

答:Error表示系統級的錯誤和程序沒必要處理的異常,是恢復不是不可能但很困難的狀況下的一種嚴重問題;好比內存溢出,不可能期望程序能處理這樣的狀況;Exception表示須要捕捉或者須要程序進行處理的異常,是一種設計或實現問題;也就是說,它表示若是程序運行正常,從不會發生的狀況。

 

52.列出一些你常見的運行時異常?

答:

ArithmeticException(算術異常)

ClassCastException (類轉換異常)

IllegalArgumentException (非法參數異常)

IndexOutOfBoundsException (下標越界異常)

NullPointerException (空指針異常)

SecurityException (安全異常)

 

 

5三、List、Set、Map是否繼承自Collection接口?

答:List、Set 是,Map 不是。Map是鍵值對映射容器,與List和Set有明顯的區別,而Set存儲的零散的元素且不容許有重複元素(數學中的集合也是如此),List是線性結構的容器,適用於按數值索引訪問元素的情形。

 

54.List、Set、Map是否繼承自Collection接口?

答:List、Set 是,Map 不是。Map是鍵值對映射容器,與List和Set有明顯的區別,而Set存儲的零散的元素且不容許有重複元素(數學中的集合也是如此),List是線性結構的容器,適用於按數值索引訪問元素的情形。

55.synchronized關鍵字的用法?

答:synchronized關鍵字能夠將對象或者方法標記爲同步,以實現對對象和方法的互斥訪問,能夠用synchronized(對象) { … }定義同步代碼塊,或者在聲明方法時將synchronized做爲方法的修飾符。在第60題的例子中已經展現了synchronized關鍵字的用法。

56.Java中有幾種類型的流?

答:字節流和字符流。字節流繼承於InputStream、OutputStream,字符流繼承於Reader、Writer。在 java.io 包中還有許多其餘的流,主要是爲了提升性能和使用方便。關於Java的I/O須要注意的有兩點:一是兩種對稱性(輸入和輸出的對稱性,字節和字符的對稱性);二是兩種設計模式(適配器模式和裝潢模式)。另外Java中的流不一樣於C#的是它只有一個維度一個方向。

面試題 - 編程實現文件拷貝。(這個題目在筆試的時候常常出現,下面的代碼給出了兩種實現方案)

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

 

public final class MyUtil {

 

    private MyUtil() {

        throw new AssertionError();

    }

 

    public static void fileCopy(String source, String target) throws IOException {

        try (InputStream in = new FileInputStream(source)) {

            try (OutputStream out = new FileOutputStream(target)) {

                byte[] buffer = new byte[4096];

                int bytesToRead;

                while((bytesToRead = in.read(buffer)) != -1) {

                    out.write(buffer, 0, bytesToRead);

                }

            }

        }

    }

 

    public static void fileCopyNIO(String source, String target) throws IOException {

        try (FileInputStream in = new FileInputStream(source)) {

            try (FileOutputStream out = new FileOutputStream(target)) {

                FileChannel inChannel = in.getChannel();

                FileChannel outChannel = out.getChannel();

                ByteBuffer buffer = ByteBuffer.allocate(4096);

                while(inChannel.read(buffer) != -1) {

                    buffer.flip();

                    outChannel.write(buffer);

                    buffer.clear();

                }

            }

        }

    }

}

注意:上面用到Java 7的TWR,使用TWR後能夠不用在finally中釋放外部資源 ,從而讓代碼更加優雅。

 

57.你在項目中哪些地方用到了XML?

答:XML的主要做用有兩個方面:數據交換和信息配置。在作數據交換時,XML將數據用標籤組裝成起來,而後壓縮打包加密後經過網絡傳送給接收者,接收解密與解壓縮後再從XML文件中還原相關信息進行處理,XML曾經是異構系統間交換數據的事實標準,但此項功能幾乎已經被JSON(JavaScript Object Notation)取而代之。固然,目前不少軟件仍然使用XML來存儲配置信息,咱們在不少項目中一般也會將做爲配置信息的硬代碼寫在XML文件中,Java的不少框架也是這麼作的,並且這些框架都選擇了dom4j做爲處理XML的工具,由於Sun公司的官方API實在不怎麼好用。

補充:如今有不少時髦的軟件(如Sublime)已經開始將配置文件書寫成JSON格式,咱們已經強烈的感覺到XML的另外一項功能也將逐漸被業界拋棄。

58.得到一個類的類對象有哪些方式?

答:

方法1:類型.class,例如:String.class

方法2:對象.getClass(),例如:"hello".getClass()

方法3:Class.forName(),例如:Class.forName("java.lang.String")

 

 

59.如何經過反射建立對象?

答:

方法1:經過類對象調用newInstance()方法,例如:String.class.newInstance()

方法2:經過類對象的getConstructor()或getDeclaredConstructor()方法得到構造器(Constructor)對象並調用其newInstance()方法建立對象,例如:String.class.getConstructor(String.class).newInstance("Hello");

60.用Java寫一個單例類。

答:

餓漢式單例

public class Singleton {

    private Singleton(){}

    private static Singleton instance = new Singleton();

    public static Singleton getInstance(){

        return instance;

    }

}

懶漢式單例

public class Singleton {

    private static Singleton instance = null;

    private Singleton() {}

    public static synchronized Singleton getInstance(){

        if (instance == null) instance = new Singleton();

        return instance;

    }

}

注意:實現一個單例有兩點注意事項,①將構造器私有,不容許外界經過構造器建立對象;②經過公開的靜態方法向外界返回類的惟一實例。這裏有一個問題能夠思考:Spring的IoC容器能夠爲普通的類建立單例,它是怎麼作到的呢?

 

61.冒泡排序幾乎是個程序員都寫得出來,可是面試的時候如何寫一個逼格高的冒泡排序卻不是每一個人都能作到,下面提供一個參考代碼:

import java.util.Comparator;

 

/**

 * 排序器接口(策略模式: 將算法封裝到具備共同接口的獨立的類中使得它們能夠相互替換)

 * @author nnngu

 *

 */

public interface Sorter {

 

   /**

    * 排序

    * @param list 待排序的數組

    */

   public <T extends Comparable<T>> void sort(T[] list);

 

   /**

    * 排序

    * @param list 待排序的數組

    * @param comp 比較兩個對象的比較器

    */

   public <T> void sort(T[] list, Comparator<T> comp);

}

import java.util.Comparator;

 

/**

 * 冒泡排序

 *

 * @author nnngu

 *

 */

public class BubbleSorter implements Sorter {

 

    @Override

    public <T extends Comparable<T>> void sort(T[] list) {

        boolean swapped = true;

        for (int i = 1, len = list.length; i < len && swapped; ++i) {

            swapped = false;

            for (int j = 0; j < len - i; ++j) {

                if (list[j].compareTo(list[j + 1]) > 0) {

                    T temp = list[j];

                    list[j] = list[j + 1];

                    list[j + 1] = temp;

                    swapped = true;

                }

            }

        }

    }

 

    @Override

    public <T> void sort(T[] list, Comparator<T> comp) {

        boolean swapped = true;

        for (int i = 1, len = list.length; i < len && swapped; ++i) {

            swapped = false;

            for (int j = 0; j < len - i; ++j) {

                if (comp.compare(list[j], list[j + 1]) > 0) {

                    T temp = list[j];

                    list[j] = list[j + 1];

                    list[j + 1] = temp;

                    swapped = true;

                }

            }

        }

    }

相關文章
相關標籤/搜索