更新時間:2019-10-15 12:00:29 來源:動力節點 瀏覽2850次
31、迭代器 Iterator 是什么?
Iterator 接口提供遍歷任何 Collection 的接口。我們可以從一個 Collection 中使用迭代器方法來獲取迭代器實例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器允許調用者在迭代過程中移除元素。
32、Iterator 怎么使用?有什么特點?
Iterator 使用代碼如下:
List
Iterator
while(it. hasNext()){
String obj = it. next();
System. out. println(obj);
}
Iterator 的特點是更加安全,因為它可以確保,在當前遍歷的集合元素被更改的時候,就會拋出 ConcurrentModificationException 異常
33、Iterator 和 ListIterator 有什么區別?
Iterator 可以遍歷 Set 和 List 集合,而 ListIterator 只能遍歷 List。
Iterator 只能單向遍歷,而 ListIterator 可以雙向遍歷(向前/后遍歷)。
ListIterator 從 Iterator 接口繼承,然后添加了一些額外的功能,比如添加一個元素、替換一個元素、獲取前面或后面元素的索引位置。
34、怎么確保一個集合不能被修改?
可以使用 Collections. unmodifiableCollection(Collection c) 方法來創建一個只讀集合,這樣改變集合的任何操作都會拋出 Java. lang. UnsupportedOperationException 異常。
示例代碼如下:
List
list. add("x");
Collection
clist. add("y"); // 運行時此行報錯
System. out. println(list. size());
三、java最新面試題及答案:Java多線程模塊
35、并行和并發有什么區別?
并行:多個處理器或多核處理器同時處理多個任務。
并發:多個任務在同一個 CPU 核上,按細分的時間片輪流(交替)執行,從邏輯上來看那些任務是同時執行。
36、線程和進程的區別?
一個程序下至少有一個進程,一個進程下至少有一個線程,一個進程下也可以有多個線程來增加程序的執行速度。
37、守護線程是什么?
守護線程是運行在后臺的一種特殊進程。它獨立于控制終端并且周期性地執行某種任務或等待處理某些發生的事件。在 Java 中垃圾回收線程就是特殊的守護線程。
38、多線程有幾種實現方式?
有4種,分別是:
繼承Thread類
實現Runnable接口
實現Callable接口通過FutureTask包裝器來創建Thread線程
通過線程池創建線程,使用線程池接口ExecutorService結合Callable、Future實現有返回結果的多線程。
前面兩種【無返回值】原因:通過重寫run方法,run方法的返回值是void,所以沒有辦法返回結果。
后面兩種【有返回值】原因:通過Callable接口,就要實現call方法,這個方法的返回值是Object,所以返回的結果可以放在Object對象中。
39、說一下 Runnable和 Callable有什么區別?
Runnable沒有返回值,Callable可以拿到有返回值,Callable可以看作是 Runnable的補充。
40、線程有哪些狀態?
線程的6種狀態:
初始(NEW):新創建了一個線程對象,但還沒有調用start()方法。
運行(RUNNABLE):Java線程中將就緒(ready)和運行中(running)兩種狀態籠統的稱為“運行”。線程對象創建后,其他線程(比如main線程)調用了該對象的start()方法。該狀態的線程位于可運行線程池中,等待被線程調度選中,獲取CPU的使用權,此時處于就緒狀態(ready)。就緒狀態的線程在獲得CPU時間片后變為運行中狀態(running)。
阻塞(BLOCKED):表示線程阻塞于鎖。
等待(WAITING):進入該狀態的線程需要等待其他線程做出一些特定動作(通知或中斷)。
超時等待(TIMED_WAITING):該狀態不同于WAITING,它可以在指定的時間后自行返回。
終止(TERMINATED):表示該線程已經執行完畢。
41、sleep() 和 wait() 有什么區別?
類的不同:sleep() 來自 Thread,wait() 來自 Object。
釋放鎖:sleep() 不釋放鎖;wait() 釋放鎖。
用法不同:sleep() 時間到會自動恢復;wait() 可以使用 notify()/notifyAll()直接喚醒。
42、notify()和 notifyAll()有什么區別?
notifyAll()會喚醒所有的線程,notify()之后喚醒一個線程。notifyAll() 調用后,會將全部線程由等待池移到鎖池,然后參與鎖的競爭,競爭成功則繼續執行,如果不成功則留在鎖池等待鎖被釋放后再次參與競爭。而 notify()只會喚醒一個線程,具體喚醒哪一個線程由虛擬機控制。
43、線程的 run() 和 start() 有什么區別?
start() 方法用于啟動線程,run() 方法用于執行線程的運行時代碼。run() 可以重復調用,而 start() 只能調用一次。
44、創建線程池有哪幾種方式?
線程池創建有七種方式,最核心的是最后一種:
newSingleThreadExecutor():它的特點在于工作線程數目被限制為 1,操作一個無界的工作隊列,所以它保證了所有任務的都是被順序執行,最多會有一個任務處于活動狀態,并且不允許使用者改動線程池實例,因此可以避免其改變線程數目;
newCachedThreadPool():它是一種用來處理大量短時間工作任務的線程池,具有幾個鮮明特點:它會試圖緩存線程并重用,當無緩存線程可用時,就會創建新的工作線程;如果線程閑置的時間超過 60 秒,則被終止并移出緩存;長時間閑置時,這種線程池,不會消耗什么資源。其內部使用 SynchronousQueue 作為工作隊列;
newFixedThreadPool(int nThreads):重用指定數目(nThreads)的線程,其背后使用的是無界的工作隊列,任何時候最多有 nThreads 個工作線程是活動的。這意味著,如果任務數量超過了活動隊列數目,將在工作隊列中等待空閑線程出現;如果有工作線程退出,將會有新的工作線程被創建,以補足指定的數目 nThreads;
newSingleThreadScheduledExecutor():創建單線程池,返回 ScheduledExecutorService,可以進行定時或周期性的工作調度;
newScheduledThreadPool(int corePoolSize):和newSingleThreadScheduledExecutor()類似,創建的是個 ScheduledExecutorService,可以進行定時或周期性的工作調度,區別在于單一工作線程還是多個工作線程;
newWorkStealingPool(int parallelism):這是一個經常被人忽略的線程池,Java 8 才加入這個創建方法,其內部會構建ForkJoinPool,利用Work-Stealing算法,并行地處理任務,不保證處理順序;
ThreadPoolExecutor():是最原始的線程池創建,上面1-3創建方式都是對ThreadPoolExecutor的封裝。
45、線程池都有哪些狀態?
RUNNING:這是最正常的狀態,接受新的任務,處理等待隊列中的任務。
SHUTDOWN:不接受新的任務提交,但是會繼續處理等待隊列中的任務。
STOP:不接受新的任務提交,不再處理等待隊列中的任務,中斷正在執行任務的線程。
TIDYING:所有的任務都銷毀了,workCount 為 0,線程池的狀態在轉換為 TIDYING 狀態時,會執行鉤子方法 terminated()。
TERMINATED:terminated()方法結束后,線程池的狀態就會變成這個。
46、線程池中 submit() 和 execute() 方法有什么區別?
execute():只能執行 Runnable 類型的任務。
submit():可以執行 Runnable 和 Callable 類型的任務。
Callable 類型的任務可以獲取執行的返回值,而 Runnable 執行無返回值。
47、在 Java 程序中怎么保證多線程的運行安全?
方法一:使用安全類,比如 Java. util. concurrent 下的類。
方法二:使用自動鎖 synchronized。
方法三:使用手動鎖 Lock。
手動鎖 Java 示例代碼如下:
Lock lock = new ReentrantLock();
lock. lock();
try {
System. out. println("獲得鎖");
} catch (Exception e) {
// TODO: handle exception
} finally {
System. out. println("釋放鎖");
lock. unlock();
}
48、多線程中 synchronized 鎖升級的原理是什么?
synchronized 鎖升級原理:在鎖對象的對象頭里面有一個 threadid 字段,在第一次訪問的時候 threadid 為空,jvm 讓其持有偏向鎖,并將 threadid 設置為其線程 id,再次進入的時候會先判斷 threadid 是否與其線程 id 一致,如果一致則可以直接使用此對象,如果不一致,則升級偏向鎖為輕量級鎖,通過自旋循環一定次數來獲取鎖,執行一定次數之后,如果還沒有正常獲取到要使用的對象,此時就會把鎖從輕量級升級為重量級鎖,此過程就構成了 synchronized 鎖的升級。
鎖的升級的目的:鎖升級是為了減低了鎖帶來的性能消耗。在 Java 6 之后優化 synchronized 的實現方式,使用了偏向鎖升級為輕量級鎖再升級到重量級鎖的方式,從而減低了鎖帶來的性能消耗。
49、什么是死鎖?
當線程 A 持有獨占鎖a,并嘗試去獲取獨占鎖 b 的同時,線程 B 持有獨占鎖 b,并嘗試獲取獨占鎖 a 的情況下,就會發生 AB 兩個線程由于互相持有對方需要的鎖,而發生的阻塞現象,我們稱為死鎖。
50、怎么防止死鎖?
盡量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),設置超時時間,超時可以退出防止死鎖。
盡量使用 Java. util. concurrent 并發類代替自己手寫鎖。
盡量降低鎖的使用粒度,盡量不要幾個功能用同一把鎖。
盡量減少同步的代碼塊。
51、ThreadLocal 是什么?有哪些使用場景?
ThreadLocal 為每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。
ThreadLocal 的經典使用場景是數據庫連接和 session 管理等。
52、說一下 synchronized 底層實現原理?
synchronized 是由一對 monitorenter/monitorexit 指令實現的,monitor 對象是同步的基本實現單元。在 Java 6 之前,monitor 的實現完全是依靠操作系統內部的互斥鎖,因為需要進行用戶態到內核態的切換,所以同步操作是一個無差別的重量級操作,性能也很低。但在 Java 6 的時候,Java 虛擬機 對此進行了大刀闊斧地改進,提供了三種不同的 monitor 實現,也就是常說的三種不同的鎖:偏向鎖(Biased Locking)、輕量級鎖和重量級鎖,大大改進了其性能。
53、synchronized 和 volatile 的區別是什么?
volatile 是變量修飾符;synchronized 是修飾類、方法、代碼段。
volatile 僅能實現變量的修改可見性,不能保證原子性;而 synchronized 則可以保證變量的修改可見性和原子性。
volatile 不會造成線程的阻塞;synchronized 可能會造成線程的阻塞。
54、synchronized 和 Lock 有什么區別?
synchronized 可以給類、方法、代碼塊加鎖;而 lock 只能給代碼塊加鎖。
synchronized 不需要手動獲取鎖和釋放鎖,使用簡單,發生異常會自動釋放鎖,不會造成死鎖;而 lock 需要自己加鎖和釋放鎖,如果使用不當沒有 unLock()去釋放鎖就會造成死鎖。
通過 Lock 可以知道有沒有成功獲取鎖,而 synchronized 卻無法辦到。
55、synchronized 和 ReentrantLock 區別是什么?
synchronized 早期的實現比較低效,對比 ReentrantLock,大多數場景性能都相差較大,但是在 Java 6 中對 synchronized 進行了非常多的改進。
主要區別如下:
ReentrantLock 使用起來比較靈活,但是必須有釋放鎖的配合動作;
ReentrantLock 必須手動獲取與釋放鎖,而 synchronized 不需要手動釋放和開啟鎖;
ReentrantLock 只適用于代碼塊鎖,而 synchronized 可用于修飾方法、代碼塊等。
ReentrantLock 標記的變量不會被編譯器優化;synchronized 標記的變量可以被編譯器優化。
56、說一下 atomic 的原理?
atomic 主要利用 CAS (Compare And Swap) 和 volatile 和 native 方法來保證原子操作,從而避免 synchronized 的高開銷,執行效率大為提升。
四、 java最新面試題及答案:Java 反射模塊
57、什么是反射?
反射是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為 Java 語言的反射機制。
58、什么是 Java 序列化?什么情況下需要序列化?
Java 序列化是為了保存各種對象在內存中的狀態,并且可以把保存的對象狀態再讀出來。
以下情況需要使用 Java 序列化:
想把的內存中的對象狀態保存到一個文件中或者數據庫中時候;
想用套接字在網絡上傳送對象的時候;
想通過RMI(遠程方法調用)傳輸對象的時候。
59、動態代理是什么?有哪些應用?
動態代理是運行時動態生成代理類。
動態代理的應用有 spring aop、hibernate 數據查詢、測試框架的后端 mock、rpc,Java注解對象獲取等。
60、怎么實現動態代理?
JDK 原生動態代理和 cglib 動態代理。JDK 原生動態代理是基于接口實現的,而 cglib 是基于繼承當前類的子類實現的。
五、java最新面試題及答案:Java對象拷貝模塊
61、為什么要使用克隆?
克隆的對象可能包含一些已經修改過的屬性,而 new 出來的對象的屬性都還是初始化時候的值,所以當需要一個新的對象來保存當前對象的“狀態”就靠克隆方法了。
62、如何實現對象克隆?
實現 Cloneable 接口并重寫 Object 類中的 clone() 方法。
實現 Serializable 接口,通過對象的序列化和反序列化實現克隆,可以實現真正的深度克隆。
63、深拷貝和淺拷貝區別是什么?
淺拷貝:當對象被復制時只復制它本身和其中包含的值類型的成員變量,而引用類型的成員對象并沒有復制。
深拷貝:除了對象本身被復制外,對象所包含的所有成員變量也將復制。
六、java最新面試題及答案:Java Web模塊
64、JSP 和 servlet 有什么區別?
JSP 是 servlet 技術的擴展,本質上就是 servlet 的簡易方式。servlet 和 JSP 最主要的不同點在于,servlet 的應用邏輯是在 Java 文件中,并且完全從表示層中的 html 里分離開來,而 JSP 的情況是 Java 和 html 可以組合成一個擴展名為 JSP 的文件。JSP 側重于視圖,servlet 主要用于控制邏輯。
65、JSP 有哪些內置對象?作用分別是什么?
JSP 有 9 大內置對象:
request:封裝客戶端的請求,其中包含來自 get 或 post 請求的參數;
response:封裝服務器對客戶端的響應;
pageContext:通過該對象可以獲取其他對象;
session:封裝用戶會話的對象;
application:封裝服務器運行環境的對象;
out:輸出服務器響應的輸出流對象;
config:Web 應用的配置對象;
page:JSP 頁面本身(相當于 Java 程序中的 this);
exception:封裝頁面拋出異常的對象。
66、說一下 JSP 的 4 種作用域?
page:代表與一個頁面相關的對象和屬性。
request:代表與客戶端發出的一個請求相關的對象和屬性。一個請求可能跨越多個頁面,涉及多個 Web 組件;需要在頁面顯示的臨時數據可以置于此作用域。
session:代表與某個用戶與服務器建立的一次會話相關的對象和屬性。跟某個用戶相關的數據應該放在用戶自己的 session 中。
application:代表與整個 Web 應用程序相關的對象和屬性,它實質上是跨越整個 Web 應用程序,包括多個頁面、請求和會話的一個全局作用域。
67、session 和 cookie 有什么區別?
session:是一種將會話狀態保存在服務器端的技術。
Cookie :是在 HTTP 協議下, Web 服務器保存在用戶瀏覽器(客戶端)上的小文本文件,它可以包含有關用戶的信息。無論何時用戶鏈接到服務器,Web 站點都可以訪問 Cookie 信息 。
存儲位置不同:session 存儲在服務器端;cookie 存儲在瀏覽器端。
安全性不同:cookie 安全性一般,在瀏覽器存儲,可以被偽造和修改。
容量和個數限制:cookie 有容量限制,每個站點下的 cookie 也有個數限制。
存儲的多樣性:session 可以存儲在 Redis 中、數據庫中、應用程序中;而 cookie 只能存儲在瀏覽器中。
68、說一下 session 的工作原理?
session 的工作原理是客戶端登錄完成之后,服務器會創建對應的 session,session 創建完之后,會把 session 的 id 發送給客戶端,客戶端再存儲到瀏覽器中。這樣客戶端每次訪問服務器時,都會帶著 sessionid,服務器拿到 sessionid 之后,在內存找到與之對應的 session 這樣就可以正常工作了。
69、如果客戶端禁止 cookie 能實現 session 還能用嗎?
可以用,session 只是依賴 cookie 存儲 sessionid,如果 cookie 被禁用了,可以使用 url 中添加 sessionid 的方式保證 session 能正常使用。
70、spring mvc 和 struts 的區別是什么?
攔截級別:struts2 是類級別的攔截;spring mvc 是方法級別的攔截。
數據獨立性:spring mvc 的方法之間基本上獨立的,獨享 request 和 response 數據,請求數據通過參數獲取,處理結果通過 ModelMap 交回給框架,方法之間不共享變量;而 struts2 雖然方法之間也是獨立的,但其所有 action 變量是共享的,這不會影響程序運行,卻給我們編碼和讀程序時帶來了一定的麻煩。
攔截機制:struts2 有以自己的 interceptor 機制,spring mvc 用的是獨立的 aop 方式,這樣導致struts2 的配置文件量比 spring mvc 大。
對 ajax 的支持:spring mvc 集成了ajax,所有 ajax 使用很方便,只需要一個注解 @ResponseBody 就可以實現了;而 struts2 一般需要安裝插件或者自己寫代碼才行。
71、如何避免 SQL 注入?
使用預處理 PreparedStatement。
使用正則表達式過濾掉字符中的特殊字符。
72、什么是 XSS 攻擊,如何避免?
XSS 攻擊:即跨站腳本攻擊,它是 Web 程序中常見的漏洞。原理是攻擊者往 Web 頁面里插入惡意的腳本代碼(css 代碼、Javascript 代碼等),當用戶瀏覽該頁面時,嵌入其中的腳本代碼會被執行,從而達到惡意攻擊用戶的目的,如盜取用戶 cookie、破壞頁面結構、重定向到其他網站等。
預防 XSS 的核心是必須對輸入的數據做過濾處理。
73、什么是 CSRF 攻擊,如何避免?
CSRF:Cross-Site Request Forgery(中文:跨站請求偽造),可以理解為攻擊者盜用了你的身份,以你的名義發送惡意請求,比如:以你名義發送郵件、發消息、購買商品,虛擬貨幣轉賬等。
防御手段:
驗證請求來源地址;
關鍵操作添加驗證碼;
在請求地址添加 token 并驗證。
由于“最常見的208道Java最新面試題及答案”內容太多,本文已滿,請看下文鏈接:
1~30道Java最新面試題及答案請看鏈接:http://www.dabaquan.cn/javazixun/2143.html
74~124道Java最新面試題及答案請看鏈接:http://www.dabaquan.cn/javazixun/2146.html
125~170道Java最新面試題及答案請看鏈接:http://www.dabaquan.cn/javazixun/2148.html
171~208道Java最新面試題及答案請看鏈接:http://www.dabaquan.cn/javazixun/2149.html
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習