Java基礎知識面試題及答案-整理


1.String類可以被繼承嗎?

 不能。String類在聲明中使用final關鍵字修飾符。使用final關鍵字修飾的類無法被繼承。

Java語言的開發者為什么要將String類定義為final類呢?

•因為當字符串是不可變的,字符串池才有可能實現。字符串池的實現可以在運行時節約很多的堆空間,因為不懂的字符串變量都指向池中的同一個字符串。如果字符串是可變的,那么字符串的駐留將不可能實現,因為這樣的話,

如果變量改變了它的值,那么其他指向這個值的變量也會一起改變。如果字符串是可變的那邊會引起很嚴重的安全問題。

•因為字符串是不可變的,所以是多線程安全的。同一個字符串實例可以可以被多個線程共享。這樣便不用因為線程安全問題而使用同步。

•因為字符串是不可變的,所以在它創建的時候HashCode就被緩存了,不需要重新計算。這就使得字符串很適合作為Map中的鍵,字符串中的處理速度要快於其他的鍵對象。這就是HashMap中的鍵往往都使用字符串。

2.final修飾符在Java中有什么用?

•final修飾的變量叫做常量,常量必須初始化,初始化后的值不能被修改。

•final修飾的方法不能被重載也不能被重寫。

•final修飾的類叫最終類,該類不能被繼承。

3.JDK和JRE有什么區別?

JDK:Java Development Kit的簡稱,Java開發工具包,包含Java開發環境和運行環境。

JRE:Java Runtime Enviroment的簡稱,Java運行環境,為Java的運行提供了所需的環境。

4.==和equals的區別是什么?

 •==對於基本數據類型和引用類型的作用效果是不同,對於基本數據類型比較的值是否相等,對於引用類型比較的應用是否相等。

•equals默認情況先比較的引用是否相等,只是很多類重寫了Object類的equals方法,比如String,Integer把equals方法變成了比較的值是否相等,所以一般情況下equals比較的是值是否相等。

5.&和&&的區別?

 &和&&在程序中最終的運算結果是一致的,區別在於:

•&運算符是:邏輯與,&不管左邊表達式的結果是true還是false,右邊的表達式都一定會執行;&運算符還可以使用在二進制位運算上。

•&&運算符是:短路與,&&運算符當左邊的表達式結果是false時,右邊的表達式不執行,存在短路現象。

6.重載(overload)和重寫(override)的區別?

方法的重載和重寫都是實現多態的方式,區別在於:

•重載實現的是編譯時的多態性;重載發生在一個類中,同名的方法如果有不同的參數列表(參數個數,參數類型,順序不同)則視為重載。

•重載實現的是運行時的多態性;重寫發生在子類與父類之間,重寫要求子類重寫父類的方法后與父類重寫的方法有相同的返回類型,比父類被重寫方法更好訪問,不能比父類被重寫方法聲明更多的異常(里氏代換原則)。

方法重寫的規則:

•參數列表、方法名、返回值類型必須完全一致;

•構造方法不能被重寫;

•聲明為 final 的方法不能被重寫;

•聲明為 static 的方法不存在重寫(重寫和多態聯合才有意義);

•訪問權限不能比父類更低;

•重寫之后的方法不能拋出更寬泛的異常;

7.為什么方法不能根據返回類型來區分重載?

在Java語言中,調用一個方法,即使這個方法有返回值,我們也可以不接收這個返回值,例如以上兩個方法doSome(),Java編譯器無法區分調用的具體是哪個方法。所以對於編譯器來說,
doSome()方法不是重載而是重復了,編譯器報錯。所以區分這兩個方法不能依靠方法的返回值類型。
8.抽象類(abstract)和接口(interface)有何異同?
•在實現方面:抽象類的子類用extends關鍵字來繼承;接口必須使用impelements關鍵字來實現接口。
•關於構造函數:抽象類可以有構造函數,接口不能有。
•關於main方法:抽象了可以有mian方法,並且我們能夠運行它,但接口不能有。
•在實現數量:類可以實現多個接口,但只能繼承一個抽象類。
•關於訪問修飾符:接口中的方法默認的修飾符是public;抽象類中的訪問修飾符可以是任意訪問修飾符。
9.String str = "i" 和String str = new String("1")一樣嗎?
不一樣,因為內存的分配方式不一樣。String str = "i"的方式JVM會將其分配到常量池中,而String str = new String("i")JVM會將其分配到堆內存中。
10.闡述靜態變量和實例變量的區別?
不管創建多少個對象,靜態變量在內存中有且僅有一個;實例變量必須依存於某一實例,需要先創建對象然后通過對象才能訪問到它。靜態變量可以實現讓多個對象共享內存。
11.String s = "Hello";s = s + " world!";這兩行代碼執行后,原始的 String 對象中的內容變了沒有?
沒有,因為 String被設計成不可變類,所以它的所有對象都是不可變對象。在這段代碼中,s原先指向一個 String 對象,內容是 "Hello",然后對 s 進行了“+”操作,但是 s 所指向的那個對象是還是沒有改變,這時s不指向原來那個對象,而指向了另一個 String 對象,內容為"Hello world!",原來那個對象還存在於內存之中,只是 s 這個引用變量不再指向它。
12.Java 中操作字符串都有哪些類?它們之間有什么區別?
操作字符串的類有:String、StringBuffer、StringBuilder。
String 和 StringBuffer、StringBuilder 的區別在於 String 聲明的是不可變的對象,每次操作都會生成新的 String 對象,再將指針指向新的 String 對象,而 StringBuffer 、 StringBuilder 可以在原有對象的基礎上進行操作,所以在經常改變字符串內容的情況下最好不要使用 String。
StringBuffer 和 StringBuilder 最大的區別在於,StringBuffer 是線程安全的,而 StringBuilder 是非線程安全的,但 StringBuilder 的性能卻高於 StringBuffer,所以在單線程環境下推薦使用 StringBuilder,多線程環境下推薦使用 StringBuffer。
13.抽象類一定要有抽象方法嗎?
不需要,抽象類不一定要有抽象方法。
14.Java中IO流分為幾種?
按功能來分:輸入流(input),輸出流(outpu)。
按類型來分:字節流和字符流。
15.BIO、NIO和AIO有什么區別?

BIO:Block IO 同步阻塞式 IO,就是我們平常使用的傳統 IO,它的特點是模式簡單使用方便,並發處理能力低。

NIO:New IO 同步非阻塞 IO,是傳統 IO 的升級,客戶端和服務器端通過 Channel(通道)通訊,實現了多路復用。

AIO:Asynchronous IO 是 NIO 的升級,也叫 NIO2,實現了異步非堵塞 IO ,異步 IO 的操作基於事件和回調機制。

16.普通類和抽象類有什么區別?

•普通類不能包含抽象方法,抽象類可以包含抽象方法。

•普通類可以直接實例化,而抽象類不能被直接實例化。

  17.Files常用的方法都有那些?
•Files.exists();檢測文件路徑是否存在。
•Files.createFile();創建文件。
•Files.createDirectory();創建目錄。
•Files.delete();刪除一個文件或者目錄。
•Files.copy();復制一個文件。
•Files.move();移動一個文件。
•Files.size();查看文件個數。
•Files.read();讀取文件。
•Files.write();寫入文件。
18.String類的常用方法有哪些?
•indexof();返回指定字符的的索引。
•charAt();返回指定索引處的字符。
•replace();字符串替換。
•trim();去除字符串兩端空格。
•splt();字符串分割,返回分割后的字符串數組。
•getBytes();返回字符串byte類型數組。
•length();返回字符串長度。
•toLowerCase();將字符串轉換為小寫字母。
•toUpperCase();將字符串轉換為大寫字母。
•substring();字符串截取。
•equals();比較字符串是否相等。
19.簡述Java math類中三個方法ceil,floor,round。
•ceil()方法表示向上取整。Math.ceil(12.3)的結果是13,Math.ceil(-12.7)的結果是12。
•floor()方法表示向下取整。Math.floor(12.7)的結果是12,Math.floor(-12.3)的結果是-13。
•round()方法表示"四舍五入"。Math.round(12.3)的結果是12,Math.round(-12.7)的結果是-13。
20.char型變量中能否能不能存儲一個中文漢字,為什么?
char可以存儲一個中文漢字,因為Java中使用的編碼是Unicode(不選擇不選擇任何特定的編碼,直接使用字符在字符集中的編號,這是統一的唯一方法),一個char 類型占2個字節(16 比特),所以放一個中文是沒問題的。
21.簡述servlet(服務連接器)的生命周期
servlet簡介:稱為小服務程序或者服務連接器,用Java編寫的服務器端程序,具有獨立平台和協議的特性,主要的功能是在於交互式地瀏覽和生成數據,生成動態的web數據。
servlet的生命周期是指servlet從加載、實例化、初始化、服務(請求處理)到銷毀的一個過程,也就是servlet從出生到結束。
服務器啟動時或者第一次請求servlet時,就會初始化一個servlet對象,就會執行初始化方法init(servletConfig),該servlet去處理客戶端請求,service(ServeltRequset req,ServeltResponse res)方法中執行,最后服務器關閉時,才會銷毀這個servlet。
22.cookie的弊端?
•安全隱患,cookie使用明文傳輸,如果有人攔截了cookie則可以獲取所有的session信息。
•cooke的數量和長度限制,每個domian最多只能有20條cookie,每個cookie長度不能超過4KB,否則會被截掉。
最多只能有20條cookie,每個cookie長度不能超過4KB,否則會被截掉。
22.Session的生命周期?
Session生效:
Sessinon在用戶第一次訪問服務器時創建,需要注意只有訪問JSP、Servlet等程序時才會創建Session,只訪問HTML、IMAGE等靜態資源並不會創建Session,可調用request.getSession(true)強制生成Session。
Session失效:
1.服務器會把長時間沒有活動的Session從服務器內存中清除,此時Session便失效。Tomcat中Session的默認失效時間為20分鍾。
2.調用Session的invalidate方法。
23.JSP和Servlet的區別?
1、jsp經編譯后就變成了Servlet。
2、jsp更擅長表現於頁面顯示,servlet更擅長於邏輯控制。
3、Servlet中沒有內置對象,Jsp中的內置對象都是必須通過HttpServletResponse對象以及HttpServlet對象得到。
4、而Servlet則是個完整的Java類,這個類的Service方法用於生成對客戶端的響應。

以上來源於鏈接:https://www.jianshu.com/p/5c03f7f4588f,如造成影響請聯系我刪除!
 
24.Java中HashMap的底層原理?

HashMap是基於hashing的原理,我們使用put(key, value)存儲對象到HashMap中,使用get(key)從HashMap中獲取對象。當我們給put()方法傳遞鍵和值時,我們先對鍵調用hashCode()方法,返回的hashCode用於找到bucket位置來儲存Entry對象。”這里關鍵點在於指出,HashMap是在bucket中儲存鍵對象和值對象,作為Map.Entry。這一點有助於理解獲取對象的邏輯。如果你沒有意識到這一點,或者錯誤的認為僅僅只在bucket中存儲值的話,你將不會回答如何從HashMap中獲取對象的邏輯。這個答案相當的正確,也顯示出面試者確實知道hashing以及HashMap的工作原理。但是這僅僅是故事的開始,當面試官加入一些Java程序員每天要碰到的實際場景的時候,錯誤的答案頻現。下個問題可能是關於HashMap中的碰撞探測(collision detection)以及碰撞的解決方法:

“當兩個對象的hashcode相同會發生什么?” 從這里開始,真正的困惑開始了,一些面試者會回答因為hashcode相同,所以兩個對象是相等的,HashMap將會拋出異常,或者不會存儲它們。然后面試官可能會提醒他們有equals()和hashCode()兩個方法,並告訴他們兩個對象就算hashcode相同,但是它們可能並不相等。一些面試者可能就此放棄,而另外一些還能繼續挺進,他們回答“因為hashcode相同,所以它們的bucket位置相同,‘碰撞’會發生。因為HashMap使用鏈表存儲對象,這個Entry(包含有鍵值對的Map.Entry對象)會存儲在鏈表中。”這個答案非常的合理,雖然有很多種處理碰撞的方法,這種方法是最簡單的,也正是HashMap的處理方法。但故事還沒有完結,面試官會繼續問:

“如果兩個鍵的hashcode相同,你如何獲取值對象?” 面試者會回答:當我們調用get()方法,HashMap會使用鍵對象的hashcode找到bucket位置,然后獲取值對象。面試官提醒他如果有兩個值對象儲存在同一個bucket,他給出答案:將會遍歷鏈表直到找到值對象。面試官會問因為你並沒有值對象去比較,你是如何確定確定找到值對象的?除非面試者直到HashMap在鏈表中存儲的是鍵值對,否則他們不可能回答出這一題。

其中一些記得這個重要知識點的面試者會說,找到bucket位置之后,會調用keys.equals()方法去找到鏈表中正確的節點,最終找到要找的值對象。完美的答案!

許多情況下,面試者會在這個環節中出錯,因為他們混淆了hashCode()和equals()方法。因為在此之前hashCode()屢屢出現,而equals()方法僅僅在獲取值對象的時候才出現。一些優秀的開發者會指出使用不可變的、聲明作final的對象,並且采用合適的equals()和hashCode()方法的話,將會減少碰撞的發生,提高效率。不可變性使得能夠緩存不同鍵的hashcode,這將提高整個獲取對象的速度,使用String,Interger這樣的wrapper類作為鍵是非常好的選擇。

如果你認為到這里已經完結了,那么聽到下面這個問題的時候,你會大吃一驚。“如果HashMap的大小超過了負載因子(load factor)定義的容量,怎么辦?”除非你真正知道HashMap的工作原理,否則你將回答不出這道題。默認的負載因子大小為0.75,也就是說,當一個map填滿了75%的bucket時候,和其它集合類(如ArrayList等)一樣,將會創建原來HashMap大小的兩倍的bucket數組,來重新調整map的大小,並將原來的對象放入新的bucket數組中。這個過程叫作rehashing,因為它調用hash方法找到新的bucket位置。

如果你能夠回答這道問題,下面的問題來了:“你了解重新調整HashMap大小存在什么問題嗎?”你可能回答不上來,這時面試官會提醒你當多線程的情況下,可能產生條件競爭(race condition)。

當重新調整HashMap大小的時候,確實存在條件競爭,因為如果兩個線程都發現HashMap需要重新調整大小了,它們會同時試着調整大小。在調整大小的過程中,存儲在鏈表中的元素的次序會反過來,因為移動到新的bucket位置的時候,HashMap並不會將元素放在鏈表的尾部,而是放在頭部,這是為了避免尾部遍歷(tail traversing)。如果條件競爭發生了,那么就死循環了。這個時候,你可以質問面試官,為什么這么奇怪,要在多線程的環境下使用HashMap呢?:)

熱心的讀者貢獻了更多的關於HashMap的問題:

1.為什么String, Interger這樣的wrapper類適合作為鍵? String, Interger這樣的wrapper類作為HashMap的鍵是再適合不過了,而且String最為常用。因為String是不可變的,也是final的,而且已經重寫了equals()和hashCode()方法了。其他的wrapper類也有這個特點。不可變性是必要的,因為為了要計算hashCode(),就要防止鍵值改變,如果鍵值在放入時和獲取時返回不同的hashcode的話,那么就不能從HashMap中找到你想要的對象。不可變性還有其他的優點如線程安全。如果你可以僅僅通過將某個field聲明成final就能保證hashCode是不變的,那么請這么做吧。因為獲取對象的時候要用到equals()和hashCode()方法,那么鍵對象正確的重寫這兩個方法是非常重要的。如果兩個不相等的對象返回不同的hashcode的話,那么碰撞的幾率就會小些,這樣就能提高HashMap的性能。

2.我們可以使用自定義的對象作為鍵嗎? 這是前一個問題的延伸。當然你可能使用任何對象作為鍵,只要它遵守了equals()和hashCode()方法的定義規則,並且當對象插入到Map中之后將不會再改變了。如果這個自定義對象時不可變的,那么它已經滿足了作為鍵的條件,因為當它創建之后就已經不能改變了。

3.我們可以使用CocurrentHashMap來代替Hashtable嗎?這是另外一個很熱門的面試題,因為ConcurrentHashMap越來越多人用了。我們知道Hashtable是synchronized的,但是ConcurrentHashMap同步性能更好,因為它僅僅根據同步級別對map的一部分進行上鎖。ConcurrentHashMap當然可以代替HashTable,但是HashTable提供更強的線程安全性。

25.http和https的區別?

•https協議需要到CA  (Certificate Authority,證書頒發機構)申請證書,一般免費證書較少,因而需要一定費用。(原來網易官網是http,而網易郵箱是https。)

•http是超文本傳輸協議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協議。

•http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。

•http的連接很簡單,是無狀態的。Https協議是由SSL+Http協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全。(無狀態的意思是其數據包的發送、傳輸和接收都是相互獨立的。無連接的意思是指通信雙方都不長久的維持對方的任何信息。)。

 26.時間復雜度和空間復雜度? 

算法的性能分析是算法設計中非常重要的方面,要想編寫出能高效運行的程序,我們就需要考慮到算法的效率。 
算法的效率主要由以下兩個復雜度來評估:

 
時間復雜度:評估執行程序所需的時間。可以估算出程序對處理器的使用程度。算法的時間復雜度一般是問題規模的函數,通常用T=T(n)表示,其中,n表示問題的規模,即算法所處理的數據量。T表示算法所用時間。

算法的執行時間=該算法所有語句執行次數(包括重復執行次數)* 執行每條語句所花費時間總和。由於每條語句的執行時間是cpu速度決定的,對計算機而言是常數,因此可以忽略不計,只考慮語句的執行次數(頻率或頻度)。為了進一步簡化計算,可以只用算法中某條重要語句(執行時間最長的語句)的執行頻度。換句話說就是時間復雜度是主要語句頻度的倍數。

備注:一個算法執行所耗費的時間,從理論上是不能算出來的,必須上機運行測試才能知道。但我們不可能也沒有必要對每個算法都上機測試,只需知道哪個算法花費的時間多,哪個算法花費的時間少就可以了。並且一個算法花費的時間與算法中語句的執行次數成正比例,哪個算法中語句執行次數多,它花費時間就多。一個算法中的語句執行次數稱為語句頻度或時間頻度。記為T(n)。

 
空間復雜度:評估執行程序所需的存儲空間。可以估算出程序對計算機內存的使用程度。不包括算法程序代碼和所處理的數據本身所占空間部分。通常用所使用額外空間的字節數表示。其算法比較簡單,記為S=S(n),其中,n表示問題規模。

設計算法時,一般是要先考慮系統環境,然后權衡時間復雜度和空間復雜度,選取一個平衡點。不過,時間復雜度要比空間復雜度更容易產生問題,因此算法研究的主要也是時間復雜度,不特別說明的情況下,復雜度就是指時間復雜度。 

評價算法時間復雜度大小需要考慮的因素:

1,計算機硬件系統的運行速度。

2,所使用的軟件環境。

3,算法本身的策略,采用不同的存儲結構和不同的算法過程,是影響時間復雜度的本質原因之一。

4,所處理的數據量多少。

算法性能的評價方法:

1,事后統計法。

2,預先計算估算法。

 1>精確計算法

 2>近似估算法

這里我介紹數據結構最常用的方法,也就是第二種的第二類。

T(n)=O(f(n));S(n)=O(g(n))

其中,f(n)和g(n)是一個已知的函數,作為計較的尺度。

通常的比較尺度有:

O(1)稱為常量級,算法的時間復雜度是一個常數。

O(n)稱為線性級,時間復雜度是數據量n的線性函數。

O(n²)稱為平方級,與數據量n的二次多項式函數屬於同一數量級。

O(n³)稱為立方級,是n的三次多項式函數。

O(logn)稱為對數級,是n的對數函數。

O(nlogn)稱為介於線性級和平方級之間的一種數量級

O(2ⁿ)稱為指數級,與數據量n的指數函數是一個數量級。

O(n!)稱為階乘級,與數據量n的階乘是一個數量級。

 

它們之間的關系是: O(1)<O(logn)<O(n)<O(nlogn)<O(n²)<O(n³)<O(2ⁿ)<O(n!)

 

 
 如果覺得對你有幫助的話,可以下面掃一掃支持一下哦!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM