java 面試題 答案(2018年)
1.jvm的理解:
java虛擬機器記憶體分5個部分,程式計數器、java虛擬機器棧、本地方法棧、堆、方法區。
程式計數器記錄當前程式碼執行位置,進行程式碼流程控制,多執行緒時記錄當前執行緒執行的位置,從而記錄執行緒返回時上一次執行到哪了,程式計數器是一個很小的記憶體空間,每個執行緒都有一個程式計數器,隨著執行緒的啟動而建立執行緒的結束而消亡,不會出現OutOfMemoryError。
java虛擬機器棧,java虛擬機器會為每一個即將執行的方法分配一個叫“棧幀”的區域,記錄該方法執行過程中所需要記錄的資訊(區域性變量表、運算元棧、動態連結,方法出口等資訊),方法執行時需要建立的區域性變數被存放在區域性變量表中,當方法執行完後這個這個方法所對應的棧幀將會出棧,釋放空間,java虛擬機器棧也是隨著執行緒的建立而建立,執行緒的結束而釋放,會出現2中異常:StackOverFlowError和OutOfMemoryError
本地方法棧和java虛擬機器棧類似,只不過是用來執行本地方法的記憶體模型。
堆是用來存放物件的記憶體空降,幾乎所有的物件都存放在堆中,java中堆時記憶體共享的隨著虛擬機器的啟動而建立,堆是垃圾回收的主要場所,又可以分為新生代和老年代,堆的大小是可以擴充套件的,但也會丟擲OutOfMemoryError。
方法區是堆的一個邏輯部分,存放著已經被虛擬機器載入的類的資訊、常量、靜態變數、編輯後的程式碼等,方法區是記憶體共享的,整個虛擬機器只有一個方法區,可以看做是堆的老年代,這裡回收效率比較低,主要回收目標是對常量池的回收和型別的解除安裝。
2.java類建立的過程
當虛擬機器遇到一個new指令時,檢查常量池中是否有該物件所屬類的符號引用,如果沒有則丟擲ClassNotFoundExecption異常,如果有,則檢查這個符號所代表的類是否已經被jvm載入,如果沒有被載入,則找到該類的class檔案並載入進方法區,如果已經載入,則根據方法區資訊為該物件在堆中分配一塊記憶體空間指給新的物件。
3.如何判斷哪些物件需要回收
引用計數法:每個物件都有一個計數器,當這個物件被引用時計數器加1,不被引用時減1,當這個計數器為0時則認為這個物件時無效物件。
可達性分析法:所有和gc roots(java虛擬機器棧所引用的物件、方法區中靜態屬性和常量應用的物件、本地方法棧所引用的物件)有直接或間接關係的物件認為是有效物件,和gc roots沒有關係的物件認為是無效物件。
4.java類例項建立的過程
先父類後子類;父類靜態-子類靜態-父類初始化塊-父類構造方法-子類初始化塊-子類構造方法。
5.synchronized與lock的區別
synchronized在同步塊執行完成或者發生異常時釋放鎖,lock必須在finally中釋放鎖,不然容易死鎖;synchronized假如執行緒A獲得鎖,執行緒B執行緒等待,如果執行緒A阻塞,則執行緒B一直等待lock有多種獲取鎖的方法,B可以不用等待嘗試去獲取鎖;synchronized鎖是非公平的,lock可以公平也可以非公平;synchronized適用於少量的程式碼同步,lock適用於大量的程式碼同步。
6.反射中,Class.forName和ClassLoader區別
java類載入的過程包括:載入->驗證->準備->解析->初始化->使用->解除安裝,而初始化就是啟用java類中靜態變數初始化程式碼和靜態程式碼塊,並初始化程式設定的變數值。
Class.forName會執行類的初始化,而ClassLoader不會執行類的初始化。
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面試題網http://www.wityx.com/