最常見的208道Java最新面試題及答案(二)

最常見的208道Java最新面試題及答案(二)

深圳達(dá)內(nèi)教育      2022-03-28 07:10:01     10

最常見的208道Java最新面試題及答案(二),  31、迭代器 Iterator 是什么?  Iterator 接口提供遍歷任何 Collection 的接口。我們可以從一個(gè) Collection 中使用迭代器方

課程價(jià)格 請(qǐng)咨詢

上課時(shí)段: 授課校區(qū):

詳細(xì)介紹


  31、迭代器 Iterator 是什么?


  Iterator 接口提供遍歷任何 Collection 的接口。我們可以從一個(gè) Collection 中使用迭代器方法來(lái)獲取迭代器實(shí)例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器允許調(diào)用者在迭代過(guò)程中移除元素。


  32、Iterator 怎么使用?有什么特點(diǎn)?


  Iterator 使用代碼如下:


Listlist = new ArrayList<>();

Iteratorit = list. iterator();

while(it. hasNext()){

String obj = it. next();

System. out. println(obj);

}


  Iterator 的特點(diǎn)是更加安全,因?yàn)樗梢源_保,在當(dāng)前遍歷的集合元素被更改的時(shí)候,就會(huì)拋出 ConcurrentModificationException 異常



33、Iterator 和 ListIterator 有什么區(qū)別?


  Iterator 可以遍歷 Set 和 List 集合,而 ListIterator 只能遍歷 List。


  Iterator 只能單向遍歷,而 ListIterator 可以雙向遍歷(向前/后遍歷)。


  ListIterator 從 Iterator 接口繼承,然后添加了一些額外的功能,比如添加一個(gè)元素、替換一個(gè)元素、獲取前面或后面元素的索引位置。


  34、怎么確保一個(gè)集合不能被修改?


  可以使用 Collections. unmodifiableCollection(Collection c) 方法來(lái)創(chuàng)建一個(gè)只讀集合,這樣改變集合的任何操作都會(huì)拋出 Java. lang. UnsupportedOperationException 異常。


  示例代碼如下:


Listlist = new ArrayList<>();

list. add("x");

Collectionclist = Collections. unmodifiableCollection(list);

clist. add("y"); // 運(yùn)行時(shí)此行報(bào)錯(cuò)

System. out. println(list. size());



  三、java最新面試題及答案:Java多線程模塊


  35、并行和并發(fā)有什么區(qū)別?


  并行:多個(gè)處理器或多核處理器同時(shí)處理多個(gè)任務(wù)。


  并發(fā):多個(gè)任務(wù)在同一個(gè) CPU 核上,按細(xì)分的時(shí)間片輪流(交替)執(zhí)行,從邏輯上來(lái)看那些任務(wù)是同時(shí)執(zhí)行。


  36、線程和進(jìn)程的區(qū)別?


  一個(gè)程序下至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程下至少有一個(gè)線程,一個(gè)進(jìn)程下也可以有多個(gè)線程來(lái)增加程序的執(zhí)行速度。


  37、守護(hù)線程是什么?


  守護(hù)線程是運(yùn)行在后臺(tái)的一種特殊進(jìn)程。它獨(dú)立于控制終端并且周期性地執(zhí)行某種任務(wù)或等待處理某些發(fā)生的事件。在 Java 中垃圾回收線程就是特殊的守護(hù)線程。


  38、多線程有幾種實(shí)現(xiàn)方式?


  有4種,分別是:


  繼承Thread類


  實(shí)現(xiàn)Runnable接口


  實(shí)現(xiàn)Callable接口通過(guò)FutureTask包裝器來(lái)創(chuàng)建Thread線程


  通過(guò)線程池創(chuàng)建線程,使用線程池接口ExecutorService結(jié)合Callable、Future實(shí)現(xiàn)有返回結(jié)果的多線程。


  前面兩種【無(wú)返回值】原因:通過(guò)重寫run方法,run方法的返回值是void,所以沒(méi)有辦法返回結(jié)果。


  后面兩種【有返回值】原因:通過(guò)Callable接口,就要實(shí)現(xiàn)call方法,這個(gè)方法的返回值是Object,所以返回的結(jié)果可以放在Object對(duì)象中。


  39、說(shuō)一下 Runnable和 Callable有什么區(qū)別?


  Runnable沒(méi)有返回值,Callable可以拿到有返回值,Callable可以看作是 Runnable的補(bǔ)充。


  40、線程有哪些狀態(tài)?


  線程的6種狀態(tài):


  初始(NEW):新創(chuàng)建了一個(gè)線程對(duì)象,但還沒(méi)有調(diào)用start()方法。


  運(yùn)行(RUNNABLE):Java線程中將就緒(ready)和運(yùn)行中(running)兩種狀態(tài)籠統(tǒng)的稱為“運(yùn)行”。線程對(duì)象創(chuàng)建后,其他線程(比如main線程)調(diào)用了該對(duì)象的start()方法。該狀態(tài)的線程位于可運(yùn)行線程池中,等待被線程調(diào)度選中,獲取CPU的使用權(quán),此時(shí)處于就緒狀態(tài)(ready)。就緒狀態(tài)的線程在獲得CPU時(shí)間片后變?yōu)檫\(yùn)行中狀態(tài)(running)。


  阻塞(BLOCKED):表示線程阻塞于鎖。


  等待(WAITING):進(jìn)入該狀態(tài)的線程需要等待其他線程做出一些特定動(dòng)作(通知或中斷)。


  超時(shí)等待(TIMED_WAITING):該狀態(tài)不同于WAITING,它可以在指定的時(shí)間后自行返回。


  終止(TERMINATED):表示該線程已經(jīng)執(zhí)行完畢。


  41、sleep() 和 wait() 有什么區(qū)別?


  類的不同:sleep() 來(lái)自 Thread,wait() 來(lái)自 Object。


  釋放鎖:sleep() 不釋放鎖;wait() 釋放鎖。


  用法不同:sleep() 時(shí)間到會(huì)自動(dòng)恢復(fù);wait() 可以使用 notify()/notifyAll()直接喚醒。


  42、notify()和 notifyAll()有什么區(qū)別?


  notifyAll()會(huì)喚醒所有的線程,notify()之后喚醒一個(gè)線程。notifyAll() 調(diào)用后,會(huì)將全部線程由等待池移到鎖池,然后參與鎖的競(jìng)爭(zhēng),競(jìng)爭(zhēng)成功則繼續(xù)執(zhí)行,如果不成功則留在鎖池等待鎖被釋放后再次參與競(jìng)爭(zhēng)。而 notify()只會(huì)喚醒一個(gè)線程,具體喚醒哪一個(gè)線程由虛擬機(jī)控制。


  43、線程的 run() 和 start() 有什么區(qū)別?


  start() 方法用于啟動(dòng)線程,run() 方法用于執(zhí)行線程的運(yùn)行時(shí)代碼。run() 可以重復(fù)調(diào)用,而 start() 只能調(diào)用一次。


  44、創(chuàng)建線程池有哪幾種方式?


  線程池創(chuàng)建有七種方式,最核心的是最后一種:


  newSingleThreadExecutor():它的特點(diǎn)在于工作線程數(shù)目被限制為 1,操作一個(gè)無(wú)界的工作隊(duì)列,所以它保證了所有任務(wù)的都是被順序執(zhí)行,最多會(huì)有一個(gè)任務(wù)處于活動(dòng)狀態(tài),并且不允許使用者改動(dòng)線程池實(shí)例,因此可以避免其改變線程數(shù)目;


  newCachedThreadPool():它是一種用來(lái)處理大量短時(shí)間工作任務(wù)的線程池,具有幾個(gè)鮮明特點(diǎn):它會(huì)試圖緩存線程并重用,當(dāng)無(wú)緩存線程可用時(shí),就會(huì)創(chuàng)建新的工作線程;如果線程閑置的時(shí)間超過(guò) 60 秒,則被終止并移出緩存;長(zhǎng)時(shí)間閑置時(shí),這種線程池,不會(huì)消耗什么資源。其內(nèi)部使用 SynchronousQueue 作為工作隊(duì)列;


  newFixedThreadPool(int nThreads):重用指定數(shù)目(nThreads)的線程,其背后使用的是無(wú)界的工作隊(duì)列,任何時(shí)候最多有 nThreads 個(gè)工作線程是活動(dòng)的。這意味著,如果任務(wù)數(shù)量超過(guò)了活動(dòng)隊(duì)列數(shù)目,將在工作隊(duì)列中等待空閑線程出現(xiàn);如果有工作線程退出,將會(huì)有新的工作線程被創(chuàng)建,以補(bǔ)足指定的數(shù)目 nThreads;


  newSingleThreadScheduledExecutor():創(chuàng)建單線程池,返回 ScheduledExecutorService,可以進(jìn)行定時(shí)或周期性的工作調(diào)度;


  newScheduledThreadPool(int corePoolSize):和newSingleThreadScheduledExecutor()類似,創(chuàng)建的是個(gè) ScheduledExecutorService,可以進(jìn)行定時(shí)或周期性的工作調(diào)度,區(qū)別在于單一工作線程還是多個(gè)工作線程;


  newWorkStealingPool(int parallelism):這是一個(gè)經(jīng)常被人忽略的線程池,Java 8 才加入這個(gè)創(chuàng)建方法,其內(nèi)部會(huì)構(gòu)建ForkJoinPool,利用Work-Stealing算法,并行地處理任務(wù),不保證處理順序;


  ThreadPoolExecutor():是最原始的線程池創(chuàng)建,上面1-3創(chuàng)建方式都是對(duì)ThreadPoolExecutor的封裝。


  45、線程池都有哪些狀態(tài)?


  RUNNING:這是最正常的狀態(tài),接受新的任務(wù),處理等待隊(duì)列中的任務(wù)。


  SHUTDOWN:不接受新的任務(wù)提交,但是會(huì)繼續(xù)處理等待隊(duì)列中的任務(wù)。


  STOP:不接受新的任務(wù)提交,不再處理等待隊(duì)列中的任務(wù),中斷正在執(zhí)行任務(wù)的線程。


  TIDYING:所有的任務(wù)都銷毀了,workCount 為 0,線程池的狀態(tài)在轉(zhuǎn)換為 TIDYING 狀態(tài)時(shí),會(huì)執(zhí)行鉤子方法 terminated()。


  TERMINATED:terminated()方法結(jié)束后,線程池的狀態(tài)就會(huì)變成這個(gè)。


  46、線程池中 submit() 和 execute() 方法有什么區(qū)別?


  execute():只能執(zhí)行 Runnable 類型的任務(wù)。


  submit():可以執(zhí)行 Runnable 和 Callable 類型的任務(wù)。


  Callable 類型的任務(wù)可以獲取執(zhí)行的返回值,而 Runnable 執(zhí)行無(wú)返回值。


  47、在 Java 程序中怎么保證多線程的運(yùn)行安全?


  方法一:使用安全類,比如 Java. util. concurrent 下的類。


  方法二:使用自動(dòng)鎖 synchronized。


  方法三:使用手動(dòng)鎖 Lock。


  手動(dòng)鎖 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 鎖升級(jí)的原理是什么?


  synchronized 鎖升級(jí)原理:在鎖對(duì)象的對(duì)象頭里面有一個(gè) threadid 字段,在第一次訪問(wèn)的時(shí)候 threadid 為空,jvm 讓其持有偏向鎖,并將 threadid 設(shè)置為其線程 id,再次進(jìn)入的時(shí)候會(huì)先判斷 threadid 是否與其線程 id 一致,如果一致則可以直接使用此對(duì)象,如果不一致,則升級(jí)偏向鎖為輕量級(jí)鎖,通過(guò)自旋循環(huán)一定次數(shù)來(lái)獲取鎖,執(zhí)行一定次數(shù)之后,如果還沒(méi)有正常獲取到要使用的對(duì)象,此時(shí)就會(huì)把鎖從輕量級(jí)升級(jí)為重量級(jí)鎖,此過(guò)程就構(gòu)成了 synchronized 鎖的升級(jí)。


  鎖的升級(jí)的目的:鎖升級(jí)是為了減低了鎖帶來(lái)的性能消耗。在 Java 6 之后優(yōu)化 synchronized 的實(shí)現(xiàn)方式,使用了偏向鎖升級(jí)為輕量級(jí)鎖再升級(jí)到重量級(jí)鎖的方式,從而減低了鎖帶來(lái)的性能消耗。


  49、什么是死鎖?


  當(dāng)線程 A 持有獨(dú)占鎖a,并嘗試去獲取獨(dú)占鎖 b 的同時(shí),線程 B 持有獨(dú)占鎖 b,并嘗試獲取獨(dú)占鎖 a 的情況下,就會(huì)發(fā)生 AB 兩個(gè)線程由于互相持有對(duì)方需要的鎖,而發(fā)生的阻塞現(xiàn)象,我們稱為死鎖。


  50、怎么防止死鎖?


  盡量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),設(shè)置超時(shí)時(shí)間,超時(shí)可以退出防止死鎖。


  盡量使用 Java. util. concurrent 并發(fā)類代替自己手寫鎖。


  盡量降低鎖的使用粒度,盡量不要幾個(gè)功能用同一把鎖。


  盡量減少同步的代碼塊。


  51、ThreadLocal 是什么?有哪些使用場(chǎng)景?


  ThreadLocal 為每個(gè)使用該變量的線程提供獨(dú)立的變量副本,所以每一個(gè)線程都可以獨(dú)立地改變自己的副本,而不會(huì)影響其它線程所對(duì)應(yīng)的副本。


  ThreadLocal 的經(jīng)典使用場(chǎng)景是數(shù)據(jù)庫(kù)連接和 session 管理等。


  52、說(shuō)一下 synchronized 底層實(shí)現(xiàn)原理?


  synchronized 是由一對(duì) monitorenter/monitorexit 指令實(shí)現(xiàn)的,monitor 對(duì)象是同步的基本實(shí)現(xiàn)單元。在 Java 6 之前,monitor 的實(shí)現(xiàn)完全是依靠操作系統(tǒng)內(nèi)部的互斥鎖,因?yàn)樾枰M(jìn)行用戶態(tài)到內(nèi)核態(tài)的切換,所以同步操作是一個(gè)無(wú)差別的重量級(jí)操作,性能也很低。但在 Java 6 的時(shí)候,Java 虛擬機(jī) 對(duì)此進(jìn)行了大刀闊斧地改進(jìn),提供了三種不同的 monitor 實(shí)現(xiàn),也就是常說(shuō)的三種不同的鎖:偏向鎖(Biased Locking)、輕量級(jí)鎖和重量級(jí)鎖,大大改進(jìn)了其性能。


  53、synchronized 和 volatile 的區(qū)別是什么?


  volatile 是變量修飾符;synchronized 是修飾類、方法、代碼段。


  volatile 僅能實(shí)現(xiàn)變量的修改可見性,不能保證原子性;而 synchronized 則可以保證變量的修改可見性和原子性。


  volatile 不會(huì)造成線程的阻塞;synchronized 可能會(huì)造成線程的阻塞。


  54、synchronized 和 Lock 有什么區(qū)別?


  synchronized 可以給類、方法、代碼塊加鎖;而 lock 只能給代碼塊加鎖。


  synchronized 不需要手動(dòng)獲取鎖和釋放鎖,使用簡(jiǎn)單,發(fā)生異常會(huì)自動(dòng)釋放鎖,不會(huì)造成死鎖;而 lock 需要自己加鎖和釋放鎖,如果使用不當(dāng)沒(méi)有 unLock()去釋放鎖就會(huì)造成死鎖。


  通過(guò) Lock 可以知道有沒(méi)有成功獲取鎖,而 synchronized 卻無(wú)法辦到。


  55、synchronized 和 ReentrantLock 區(qū)別是什么?


  synchronized 早期的實(shí)現(xiàn)比較低效,對(duì)比 ReentrantLock,大多數(shù)場(chǎng)景性能都相差較大,但是在 Java 6 中對(duì) synchronized 進(jìn)行了非常多的改進(jìn)。


  主要區(qū)別如下:


  ReentrantLock 使用起來(lái)比較靈活,但是必須有釋放鎖的配合動(dòng)作;


  ReentrantLock 必須手動(dòng)獲取與釋放鎖,而 synchronized 不需要手動(dòng)釋放和開啟鎖;


  ReentrantLock 只適用于代碼塊鎖,而 synchronized 可用于修飾方法、代碼塊等。


  ReentrantLock 標(biāo)記的變量不會(huì)被編譯器優(yōu)化;synchronized 標(biāo)記的變量可以被編譯器優(yōu)化。


  56、說(shuō)一下 atomic 的原理?


  atomic 主要利用 CAS (Compare And Swap) 和 volatile 和 native 方法來(lái)保證原子操作,從而避免 synchronized 的高開銷,執(zhí)行效率大為提升。



  四、 java最新面試題及答案:Java 反射模塊


  57、什么是反射?


  反射是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為 Java 語(yǔ)言的反射機(jī)制。


  58、什么是 Java 序列化?什么情況下需要序列化?


  Java 序列化是為了保存各種對(duì)象在內(nèi)存中的狀態(tài),并且可以把保存的對(duì)象狀態(tài)再讀出來(lái)。


  以下情況需要使用 Java 序列化:


  想把的內(nèi)存中的對(duì)象狀態(tài)保存到一個(gè)文件中或者數(shù)據(jù)庫(kù)中時(shí)候;


  想用套接字在網(wǎng)絡(luò)上傳送對(duì)象的時(shí)候;


  想通過(guò)RMI(遠(yuǎn)程方法調(diào)用)傳輸對(duì)象的時(shí)候。


  59、動(dòng)態(tài)代理是什么?有哪些應(yīng)用?


  動(dòng)態(tài)代理是運(yùn)行時(shí)動(dòng)態(tài)生成代理類。


  動(dòng)態(tài)代理的應(yīng)用有 spring aop、hibernate 數(shù)據(jù)查詢、測(cè)試框架的后端 mock、rpc,Java注解對(duì)象獲取等。


  60、怎么實(shí)現(xiàn)動(dòng)態(tài)代理?


  JDK 原生動(dòng)態(tài)代理和 cglib 動(dòng)態(tài)代理。JDK 原生動(dòng)態(tài)代理是基于接口實(shí)現(xiàn)的,而 cglib 是基于繼承當(dāng)前類的子類實(shí)現(xiàn)的。



  五、java最新面試題及答案:Java對(duì)象拷貝模塊


  61、為什么要使用克隆?


  克隆的對(duì)象可能包含一些已經(jīng)修改過(guò)的屬性,而 new 出來(lái)的對(duì)象的屬性都還是初始化時(shí)候的值,所以當(dāng)需要一個(gè)新的對(duì)象來(lái)保存當(dāng)前對(duì)象的“狀態(tài)”就靠克隆方法了。


  62、如何實(shí)現(xiàn)對(duì)象克隆?


  實(shí)現(xiàn) Cloneable 接口并重寫 Object 類中的 clone() 方法。


  實(shí)現(xiàn) Serializable 接口,通過(guò)對(duì)象的序列化和反序列化實(shí)現(xiàn)克隆,可以實(shí)現(xiàn)真正的深度克隆。


  63、深拷貝和淺拷貝區(qū)別是什么?


  淺拷貝:當(dāng)對(duì)象被復(fù)制時(shí)只復(fù)制它本身和其中包含的值類型的成員變量,而引用類型的成員對(duì)象并沒(méi)有復(fù)制。


  深拷貝:除了對(duì)象本身被復(fù)制外,對(duì)象所包含的所有成員變量也將復(fù)制。



  六、java最新面試題及答案:Java Web模塊


  64、JSP 和 servlet 有什么區(qū)別?


  JSP 是 servlet 技術(shù)的擴(kuò)展,本質(zhì)上就是 servlet 的簡(jiǎn)易方式。servlet 和 JSP 最主要的不同點(diǎn)在于,servlet 的應(yīng)用邏輯是在 Java 文件中,并且完全從表示層中的 html 里分離開來(lái),而 JSP 的情況是 Java 和 html 可以組合成一個(gè)擴(kuò)展名為 JSP 的文件。JSP 側(cè)重于視圖,servlet 主要用于控制邏輯。


  65、JSP 有哪些內(nèi)置對(duì)象?作用分別是什么?


  JSP 有 9 大內(nèi)置對(duì)象:


  request:封裝客戶端的請(qǐng)求,其中包含來(lái)自 get 或 post 請(qǐng)求的參數(shù);


  response:封裝服務(wù)器對(duì)客戶端的響應(yīng);


  pageContext:通過(guò)該對(duì)象可以獲取其他對(duì)象;


  session:封裝用戶會(huì)話的對(duì)象;


  application:封裝服務(wù)器運(yùn)行環(huán)境的對(duì)象;


  out:輸出服務(wù)器響應(yīng)的輸出流對(duì)象;


  config:Web 應(yīng)用的配置對(duì)象;


  page:JSP 頁(yè)面本身(相當(dāng)于 Java 程序中的 this);


  exception:封裝頁(yè)面拋出異常的對(duì)象。


  66、說(shuō)一下 JSP 的 4 種作用域?


  page:代表與一個(gè)頁(yè)面相關(guān)的對(duì)象和屬性。


  request:代表與客戶端發(fā)出的一個(gè)請(qǐng)求相關(guān)的對(duì)象和屬性。一個(gè)請(qǐng)求可能跨越多個(gè)頁(yè)面,涉及多個(gè) Web 組件;需要在頁(yè)面顯示的臨時(shí)數(shù)據(jù)可以置于此作用域。


  session:代表與某個(gè)用戶與服務(wù)器建立的一次會(huì)話相關(guān)的對(duì)象和屬性。跟某個(gè)用戶相關(guān)的數(shù)據(jù)應(yīng)該放在用戶自己的 session 中。


  application:代表與整個(gè) Web 應(yīng)用程序相關(guān)的對(duì)象和屬性,它實(shí)質(zhì)上是跨越整個(gè) Web 應(yīng)用程序,包括多個(gè)頁(yè)面、請(qǐng)求和會(huì)話的一個(gè)全局作用域。


  67、session 和 cookie 有什么區(qū)別?


  session:是一種將會(huì)話狀態(tài)保存在服務(wù)器端的技術(shù)。


  cookie :是在 HTTP 協(xié)議下, Web 服務(wù)器保存在用戶瀏覽器(客戶端)上的小文本文件,它可以包含有關(guān)用戶的信息。無(wú)論何時(shí)用戶鏈接到服務(wù)器,Web 站點(diǎn)都可以訪問(wèn) cookie 信息 。


  存儲(chǔ)位置不同:session 存儲(chǔ)在服務(wù)器端;cookie 存儲(chǔ)在瀏覽器端。


  安全性不同:cookie 安全性一般,在瀏覽器存儲(chǔ),可以被偽造和修改。


  容量和個(gè)數(shù)限制:cookie 有容量限制,每個(gè)站點(diǎn)下的 cookie 也有個(gè)數(shù)限制。


  存儲(chǔ)的多樣性:session 可以存儲(chǔ)在 Redis 中、數(shù)據(jù)庫(kù)中、應(yīng)用程序中;而 cookie 只能存儲(chǔ)在瀏覽器中。


  68、說(shuō)一下 session 的工作原理?


  session 的工作原理是客戶端登錄完成之后,服務(wù)器會(huì)創(chuàng)建對(duì)應(yīng)的 session,session 創(chuàng)建完之后,會(huì)把 session 的 id 發(fā)送給客戶端,客戶端再存儲(chǔ)到瀏覽器中。這樣客戶端每次訪問(wèn)服務(wù)器時(shí),都會(huì)帶著 sessionid,服務(wù)器拿到 sessionid 之后,在內(nèi)存找到與之對(duì)應(yīng)的 session 這樣就可以正常工作了。


  69、如果客戶端禁止 cookie 能實(shí)現(xiàn) session 還能用嗎?


  可以用,session 只是依賴 cookie 存儲(chǔ) sessionid,如果 cookie 被禁用了,可以使用 url 中添加 sessionid 的方式保證 session 能正常使用。


  70、spring mvc 和 struts 的區(qū)別是什么?


  攔截級(jí)別:struts2 是類級(jí)別的攔截;spring mvc 是方法級(jí)別的攔截。


  數(shù)據(jù)獨(dú)立性:spring mvc 的方法之間基本上獨(dú)立的,獨(dú)享 request 和 response 數(shù)據(jù),請(qǐng)求數(shù)據(jù)通過(guò)參數(shù)獲取,處理結(jié)果通過(guò) ModelMap 交回給框架,方法之間不共享變量;而 struts2 雖然方法之間也是獨(dú)立的,但其所有 action 變量是共享的,這不會(huì)影響程序運(yùn)行,卻給我們編碼和讀程序時(shí)帶來(lái)了一定的麻煩。


  攔截機(jī)制:struts2 有以自己的 interceptor 機(jī)制,spring mvc 用的是獨(dú)立的 aop 方式,這樣導(dǎo)致struts2 的配置文件量比 spring mvc 大。


  對(duì) ajax 的支持:spring mvc 集成了ajax,所有 ajax 使用很方便,只需要一個(gè)注解 @ResponseBody 就可以實(shí)現(xiàn)了;而 struts2 一般需要安裝插件或者自己寫代碼才行。


  71、如何避免 SQL 注入?


  使用預(yù)處理 PreparedStatement。


  使用正則表達(dá)式過(guò)濾掉字符中的特殊字符。


  72、什么是 XSS 攻擊,如何避免?


  XSS 攻擊:即跨站腳本攻擊,它是 Web 程序中常見的漏洞。原理是攻擊者往 Web 頁(yè)面里插入惡意的腳本代碼(css 代碼、Javascript 代碼等),當(dāng)用戶瀏覽該頁(yè)面時(shí),嵌入其中的腳本代碼會(huì)被執(zhí)行,從而達(dá)到惡意攻擊用戶的目的,如盜取用戶 cookie、破壞頁(yè)面結(jié)構(gòu)、重定向到其他網(wǎng)站等。


  預(yù)防 XSS 的核心是必須對(duì)輸入的數(shù)據(jù)做過(guò)濾處理。


  73、什么是 CSRF 攻擊,如何避免?


  CSRF:Cross-Site Request Forgery(中文:跨站請(qǐng)求偽造),可以理解為攻擊者盜用了你的身份,以你的名義發(fā)送惡意請(qǐng)求,比如:以你名義發(fā)送郵件、發(fā)消息、購(gòu)買商品,虛擬貨幣轉(zhuǎn)賬等。


  防御手段:


  驗(yàn)證請(qǐng)求來(lái)源地址;


  關(guān)鍵操作添加驗(yàn)證碼;


  在請(qǐng)求地址添加 token 并驗(yàn)證。


由于“最常見的208道Java最新面試題及答案”內(nèi)容太多,本文已滿,請(qǐng)看下文鏈接:


1~30道Java最新面試題及答案請(qǐng)看鏈接:http://www.bjpowernode.com/javazixun/2143.html


74~124道Java最新面試題及答案請(qǐng)看鏈接:http://www.bjpowernode.com/javazixun/2146.html


125~170道Java最新面試題及答案請(qǐng)看鏈接:http://www.bjpowernode.com/javazixun/2148.html


171~208道Java最新面試題及答案請(qǐng)看鏈接:http://www.bjpowernode.com/javazixun/2149.html

 

Java面試題及答案

培訓(xùn)啦提醒您:交易時(shí)請(qǐng)核實(shí)對(duì)方資質(zhì),對(duì)于過(guò)大宣傳或承諾需謹(jǐn)慎!任何要求預(yù)付定金、匯款等方式均存在風(fēng)險(xiǎn),謹(jǐn)防上當(dāng)。