瞭解了這些,輕鬆拿offer——Java面試之道

本篇文章將講述Java基礎中的面試題及其解答,希望對大家有所幫助。

synchronized和Lock的區別

synchronized是JVM層面實現的,java提供的關鍵字,Lock是API層面的鎖。

  • synchronized不需要手動釋放鎖,底層會自動釋放;Lock則需要手動釋放鎖,否則有可能導致死鎖
  • synchronized等待不可中斷,除非拋出異常或者執行完成;Lock可以中斷,通過interrupt()可中斷
  • synchronized是非公平鎖;Lock是默認非公平鎖,當傳入true時是公平鎖
  • synchronized不可綁定多個條件;Lock可實現分組喚醒需要喚醒的鎖

"=="和equals方法的區別

對於"==":在基本類型下,"== "比較的是值,而在引用類型下,"=="比較的是地址。
而對於equals方法:如果調用的類中沒有實現equals方法,將會調用父類的equals方法,此時比較的是地址;而很多api中的類均已實現equals方法,它們比較的是值。

&和&&的區別

&和&&都可以用作邏輯與的運算符,當運算符兩邊的表達式的結果都爲true時,整個運算結果才爲true,否則,只要有一方爲false,則結果爲false。
&&還具有短路的功能,即如果第一個表達式爲false,則不再計算第二個表達式,直接得出結果爲false。
&還可以用作位運算符,當&操作符兩邊的表達式不是boolean類型時,&表示按位與操作,我們通常使用0x0f來與一個整數進行&運算,來獲取該整數的最低4個bit位。

什麼是可變參數

可變參數表示需要接收的參數個數可以不確定,例如:

public void show(int... nums){

}

此時該方法可以接收任意個int類型的參數。
想要獲得所有參數,就可以對nums進行遍歷,此時的nums爲參數數組。

final,finally,finalize的區別

final,意爲最終的,用於修飾類,方法和變量。
如果一個類被final修飾,意味着這個類爲最終類,它將不能再派生出新的子類,不能被繼承,否則出錯,因此在聲明類時,final和abstract無法同時出現,因爲abstract修飾的類必定要有具體的子類實現,而final不允許子類的繼承,此時陷入矛盾。
如果一個變量被final修飾,則它在程序中將不能被修改,而且必須在聲明變量時就賦值。
如果一個方法被final修飾,它將無法被子類重寫。
finally,是異常處理中的關鍵字,它表示無論異常是否被捕獲,程序都將執行finally中的代碼塊。
finalize,是Object中的方法,它的目的是保證對象在被垃圾收集前完成特定資源的回收,而事實上,這個方法具有不確定性,它並不能保證你在調用了該方法之後就會完成資源回收。

String s = new String(“abc”);創建了幾個String 對象

創建了兩個,第一個:“abc”,這種方式稱爲顯式聲明字符串,會在常量池中創建一個對象;第二個:new關鍵字會在堆中創建指向常量池字符串的引用。所以一共創建了兩個String對象。

GC是什麼?爲什麼要有GC?

GC是垃圾收集的意思,內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會導致程序或系統的不穩定甚至崩潰,Java提供的GC功能可以自動監測對象是否超過作用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯式操作方法。Java程序員不用擔心內存管理,因爲垃圾收集器會自動進行管理。要請求垃圾收集,可以調用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉顯式的垃圾回收調用。
垃圾回收可以有效的防止內存泄露,有效地使用的內存。垃圾回收器通常是作爲一個單獨的低優先級的線程運行,不可預知的情況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清除和回收,程序員不能實時地調用垃圾回收器對某個對象或所有對象進行垃圾回收。

length()和length的區別

Java中的length屬性是針對數組來說的,假設聲明一個數組,則可以通過length屬性直接獲得數組的長度;
Java中的length()方法是針對字符串String的,如果想得到字符串長度,則可以使用length()方法。

Java 創建對象的幾種方式

  1. 通過new關鍵字
  2. 通過反射
  3. 採用clone
  4. 通過序列化

throw和throws的區別

throw用於主動拋出java.lang.Throwable 類的一個實例化對象,意思是說你可以通過關鍵字 throw 拋出一個 Error 或者 一個Exception,如:throw new IllegalArgumentException(“″), 而throws 的作用是作爲方法聲明和簽名的一部分,方法被拋出相應的異常以便調用者能處理。Java 中,任何未處理的受檢查異常強制在 throws 子句中聲明。

char型變量中能不能存貯一箇中文漢字

char型變量是用來存儲Unicode編碼字符的,Unicode編碼字符集中包含了漢字,所以,char型變量可以用於存儲中文漢字。不過,如果某個特殊的漢字沒有被包含在Unicode編碼字符集中,那麼,這個char型變量中就不能存儲這個特殊漢字。

switch語句中的表達式能否使用byte類型、short類型、long類型、String類型

在switch中,例如switch(x),表達式x規定只能是一個整數表達式或者枚舉類型,這裏的整數表達式可以是int類型,也可以是Integer類型,而byte、short都可以隱式轉換爲int,所以可以使用,那麼很顯然,由於long無法隱式轉換爲int,所以long類型無法作用在switch語句中。從Java7開始,switch語句支持字符串作爲表達式。

Integer與int的區別

int是Java提供的8種原始數據類型之一。Java爲每個原始類型都提供了封裝類,Integer即爲int的封裝類。int的默認值爲0,而Integer的默認值爲null,即Integer可以區分出未賦值和值爲0的區別,int則無法表達出未賦值的情況,例如,要想表達出沒有參加考試和考試成績爲0的區別,則只能使用Integer。在JSP開發中,Integer的默認爲null,所以用el表達式在文本框中顯示時,值爲空白字符串,而int默認的默認值爲0,所以用el表達式在文本框中顯示時,結果爲0,所以,在web開發中的POJO中,你會發現int類型基本不會出現,int類型不適合作爲web開發的數據展示。

http協議和https協議的區別

HTTP:是互聯網上應用最爲廣泛的一種網絡協議,是一個客戶端和服務器端請求和應答的標準(TCP),用於從WWW服務器傳輸超文本到本地瀏覽器的傳輸協議,它可以使瀏覽器更加高效,使網絡傳輸減少。
HTTPS:是以安全爲目標的HTTP通道,簡單講是HTTP的安全版,即HTTP下加入SSL層,HTTPS的安全基礎是SSL,因此加密的詳細內容就需要SSL。
區別:

  • https協議需要到ca申請證書,一般免費證書較少,因而需要一定費用
  • http是超文本傳輸協議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協議
  • http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,後者是443
  • http的連接很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全

環境變量path和classpath的作用分別是什麼

path是配置Windows可執行文件的搜索路徑,即擴展名爲.exe的程序文件所在的目錄,用於指定DOS窗口命令的路徑。
Classpath是配置class文件所在的目錄,用於指定類搜索路徑,JVM就是通過它來尋找該類的class類文件的。

float f=1.1;是否正確

答案是錯誤,在Java中浮點數默認爲double類型,所以這裏的1.1其實是double類型,將double類型賦值給float類型會造成精度丟失,所以必須強制類型轉換才行,否則報錯。

List的三個子類的特點

ArrayList 底層結構是數組,底層查詢快,增刪慢
LinkedList 底層結構是鏈表,增刪快,查詢慢
Voctor 底層結構是數組,線程安全的,增刪慢,查詢慢

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

靜態變量屬於類,實例變量依存於某一實例
靜態變量:是被static修飾符修飾的變量,也稱爲類變量,它屬於類,不屬於類的任何一個對象,一個類不管創建多少個對象,靜態變量在內存中有且僅有一個拷貝;
實例變量:必須依存於某一實例,需要先創建對象然後通過對象才能訪問到它。靜態變量可以實現讓多個對象共享內存。

如何理解線程的優先級

在Java中,每個線程都有相應的優先級,如果沒有手動設置,則程序會有一個默認的線程優先級。一般來說,高優先級的線程在運行時會具有優先權,但這依賴於線程調度的實現,這個實現是和操作系統相關的。我們可以定義線程的優先級,但是這並不能保證高優先級的線程會在低優先級的線程前執行。線程優先級是一個int變量(從1-10),1代表最低優先級,10代表最高優先級。

String類可以被繼承嗎

String類無法被繼承,因爲String類被final關鍵字修飾

爲什麼要將String設計爲無法被繼承

因爲只有當字符串是不可變的,字符串池纔有可能實現。字符串池的實現可以在運行時節約很多堆空間,因爲不同的字符串變量都指向池中的同一個字符串。但如果字符串是可變的,那麼字符串駐留將不能實現,因爲這樣的話,如果變量改變了它的值,那麼其它指向這個值的變量的值也會一起改變。如果字符串是可變的,那麼會引起很嚴重的安全問題。譬如,數據庫的用戶名、密碼都是以字符串的形式傳入來獲得數據庫的連接,或者在socket編程中,主機名和端口都是以字符串的形式傳入。因爲字符串是不可變的,所以它的值是不可改變的,否則黑客們可以鑽到空子,改變字符串指向的對象的值,造成安全漏洞。
因爲字符串是不可變的,所以是多線程安全的,同一個字符串實例可以被多個線程共享。這樣便不用因爲線程安全問題而使用同步。字符串自己便是線程安全的。

如何跳出當前的多重嵌套循環

在最外成循環前加一個標記,然後在需要跳出循環的地方編寫break + 標記 即可跳出多重循環,例如:

public static void main(String[] args){
	x:for(int i = 0;i < 3;i++){
		for(int j = 0;j < 3;j++){
			for(int k = 0;k < 3;k++){
				break x;
			}
		}
	}
}

break和continue的區別

break和continue 都是用來控制循環的語句。
break 用於完全結束一個循環,跳出循環體執行循環後面的語句。

String s = “Hello”;s = s + " world!";這兩行代碼執行後,原始的 String 對象中的內容有沒有被改變

前面就已經說過了,String是被final修飾的,是無法修改的,那麼輸出s的內容爲什麼又是Helloworld!呢?是因爲此時的s已經不再指向原始的字符串了,它指向了新拼接的字符串Helloworld!,而原始的字符串Hello其實並沒有被改變。

同步和異步有什麼區別

如果數據將在線程間共享。例如正在寫的數據以後可能被另一個線程讀到,或者正在讀的數據可能已經被另一個線程寫過了,那麼這些數據就是共享數據,必須進行同步存取。
當應用程序在對象上調用了一個需要花費很長時間來執行的方法,並且不希望讓程序等待方法的返回時,就應該使用異步編程,在很多情況下采用異步途徑往往更有效率。

static方法內部可以調用非static方法嗎

這是絕對不可以的,因爲非static方法是要與對象關聯在一起的,必須創建一個對象後,纔可以在該對象上進行方法調用,而static方法調用時不需要創建對象,可以直接調用。也就是說,當一個static方法被調用時,可能還沒有創建任何實例對象,如果從一個static方法中發出對非static方法的調用,那個非static方法無法知曉它將關聯的對象是哪個,所以不能。

使用final關鍵字修飾一個變量時,是引用不能變,還是引用的對象不能變

使用final關鍵字修飾一個變量時,是指引用變量不能變,引用變量所指向的對象中的內容還是可以改變的。

List、Map、Set三個接口存取元素時,各有什麼特點

List以特定索引來存取元素,可以有重複元素。Set不能存放重複元素(用對象的equals()方法來區分元素是否重複)。
Map保存鍵值對映射,映射關係可以是一對一或多對一。
Set和Map容器都有基於哈希存儲和排序樹的兩種實現版本,基於哈希存儲的版本理論存取時間複雜度爲O(1),而基於排序樹版本的實現在插入或刪除元素時會按照元素或元素的鍵(key)構成排序樹從而達到排序和去重的效果。

編譯時異常和運行時異常的區別

編譯時異常在函數內被拋出,函數必須聲明,否則編譯失敗。
聲明的原因:是需要調用者對該異常進行處理。必須進行處理,否則無法編譯通過。
運行時異常如果在函數內被拋出,在函數上不需要聲明。
不聲明的原因:不需要調用者處理,運行時異常發生,已經無法再讓程序繼續運行,所以,不讓調用處理的,直接讓程序停止,由調用者對代碼進行修正。

wait( )和sleep( )的區別

  • sleep( )沒有釋放同步鎖,而wait( )釋放了同步鎖
  • sleep( )必須制定時間,而wait( )不用
  • sleep()可以在任何地方使用,而wait( )、notify( )、notifyAll( )只能在同步方法或同步代碼塊中使用;
  • sleep()必須捕獲異常,而wait( )、notify( )、notifyAll( )不用

Java中如何實現序列化,有什麼意義?

序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。可以對流化後的對象進行讀寫操作,也可將流化後的對象傳輸於網絡之間。序列化是爲了解決對象流讀寫操作時可能引發的問題(如果不進行序列化可能會存在數據亂序的問題)。

要實現序列化,需要讓一個類實現Serializable接口,該接口是一個標識性接口,標註該類對象是可被序列化的,然後使用一個輸出流來構造一個對象輸出流並通過writeObject(Object)方法就可以將實現對象寫出(即保存其狀態);如果需要反序列化則可以用一個輸入流建立對象輸入流,然後通過readObject方法從流中讀取對象。

例如,在web開發中,如果對象被保存在了Session中,tomcat在重啓時要把Session對象序列化到硬盤,這個對象就必須實現Serializable接口。如果對象要經過分佈式系統進行網絡傳輸或通過rmi等遠程調用,這就需要在網絡上傳輸對象,被傳輸的對象就必須實現Serializable接口。

發佈了115 篇原創文章 · 獲贊 9041 · 訪問量 69萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章