Java經(jīng)典面試題最全匯總208道(三)
前言
短時(shí)間提升自己最快的手段就是背面試題,最近總結(jié)了Java常用的面試題,分享給大家,希望大家都能圓夢(mèng)大廠,加油,我命由我不由天。
websocket應(yīng)用的是哪個(gè)協(xié)議
WebSocket是一個(gè)允許Web應(yīng)用程序(通常指瀏覽器)與服務(wù)器進(jìn)行雙向通信的協(xié)議。
HTML5的WebSocket API主要是為瀏覽器端提供了一個(gè)基于TCP協(xié)議實(shí)現(xiàn)全雙工通信的方法。
WebSocket優(yōu)勢(shì): 瀏覽器和服務(wù)器只需要要做一個(gè)握手的動(dòng)作,在建立連接之后,雙方可以在任意時(shí)刻,相互推送信息。
同時(shí),服務(wù)器與客戶端之間交換的頭信息很小。
106、說(shuō)一下 tcp 粘包是怎么產(chǎn)生的?
發(fā)送方需要等緩沖區(qū)滿才能發(fā)送出去,造成粘包;
接收方不及時(shí)接收緩沖區(qū)的包,造成粘包;
107、請(qǐng)列舉出在 JDK 中幾個(gè)常用的設(shè)計(jì)模式?
1、單例模式
作用:保證類只有一個(gè)實(shí)例。
JDK中體現(xiàn):Runtime類。
2、靜態(tài)工廠模式
作用:代替構(gòu)造函數(shù)創(chuàng)建對(duì)象,方法名比構(gòu)造函數(shù)清晰。
JDK中體現(xiàn):Integer.valueOf、Class.forName
3、抽象工廠
作用:創(chuàng)建某一種類的對(duì)象。
JDK中體現(xiàn):Java.sql包。
4、原型模式
clone();
原型模式的本質(zhì)是拷貝原型來(lái)創(chuàng)建新的對(duì)象,拷貝是比new更快的創(chuàng)建對(duì)象的方法,當(dāng)需要大批量創(chuàng)建新對(duì)象而且都是同一個(gè)類的對(duì)象的時(shí)候考慮使用原型模式。
一般的克隆只是淺拷貝(對(duì)象的hash值不一樣,但是對(duì)象里面的成員變量的hash值是一樣的)。
有些場(chǎng)景需要深拷貝,這時(shí)我們就要重寫clone方法,以ArrayList為例:
5、適配器模式
作用:使不兼容的接口相容。
JDK中體現(xiàn):InputStream、OutputStream。
6、裝飾器模式
作用:為類添加新的功能,防止類繼承帶來(lái)的類爆炸。
JDK中體現(xiàn):io類、Collections、List。
7、外觀模式
作用:封裝一組交互類,一直對(duì)外提供接口。
JDK中體現(xiàn):logging包。
8、享元模式
作用:共享對(duì)象、節(jié)省內(nèi)存。
JDK中體現(xiàn):Integer.valueOf、String常量池。
9、代理模式
作用:
(1)透明調(diào)用被代理對(duì)象,無(wú)須知道復(fù)雜實(shí)現(xiàn)細(xì)節(jié);
(2)增加被代理類的功能;
JDK中體現(xiàn):動(dòng)態(tài)代理。
10、迭代器模式
作用:將集合的迭代和集合本身分離。
JDK中體現(xiàn):Iterator
11、命令模式
作用:封裝操作,使接口一致。
JDK中體現(xiàn):Runable、Callable、ThreadPoolExecutor。
108、什么是設(shè)計(jì)模式?你是否在你的代碼里面使用過(guò)任何設(shè)計(jì)模式?
1、什么是設(shè)計(jì)模式?
設(shè)計(jì)模式是解決軟件開(kāi)發(fā)某些特定問(wèn)題而提出的一些解決方案,也可以理解為解決問(wèn)題的一些固定思路。
通過(guò)設(shè)計(jì)模式可以幫助我們?cè)鰪?qiáng)代碼的可復(fù)用性、可擴(kuò)展性、靈活性。
我們使用設(shè)計(jì)模式的最終目的是實(shí)現(xiàn)代碼的高內(nèi)聚、低耦合。
2、設(shè)計(jì)模式的七大原則
單一職責(zé)原則接口隔離原則依賴倒轉(zhuǎn)原則里式替換原則開(kāi)閉原則迪米特法則合成復(fù)用原則
3、你是否在你的代碼里面使用過(guò)任何設(shè)計(jì)模式?
(1)單例模式
JDK種的runtime,Spring種的singeton。
(2)簡(jiǎn)單工廠模式
Spring的BeanFactory,根據(jù)傳入一個(gè)唯一標(biāo)識(shí)來(lái)獲得bean對(duì)象。
(3)原型模式
clone()
(4)代理模式
Spring的AOP中,Spring實(shí)現(xiàn)AOP功能的原理就是代理模式,①JDK動(dòng)態(tài)代理。②CGLIB動(dòng)態(tài)代理,使用Advice(通知)對(duì)類進(jìn)行方法級(jí)別的切面增強(qiáng)。
(5)裝飾器模式
為類添加新的功能,防止類爆炸;
IO流、數(shù)據(jù)源包裝,Spring中用到的裝飾器模式表現(xiàn)在Wrapper。
109、Java 中什么叫單例設(shè)計(jì)模式?請(qǐng)用 Java 寫出線程安全的單例模式
- 保證程序只有一個(gè)對(duì)象的實(shí)例,叫做單例模式;
- 內(nèi)部類的方式實(shí)現(xiàn)單例模式,是線程安全的;
- 雙重驗(yàn)證方式實(shí)現(xiàn)單例模式也是線程安全的;
110、在 Java 中,什么叫觀察者設(shè)計(jì)模式(observer design pattern)?
1、觀察者模式是一種一對(duì)多的依賴關(guān)系,讓多個(gè)觀察者同時(shí)監(jiān)聽(tīng)某一主題對(duì)象。當(dāng)這個(gè)主題對(duì)象發(fā)生變化時(shí),會(huì)通知所有觀察者對(duì)象,使它們能夠自動(dòng)更新自己。
2、Java提供的對(duì)觀察者模式的支持
在Java語(yǔ)言的java.util庫(kù)里面,提供了一個(gè)Observable類以及一個(gè)Observer接口,構(gòu)成Java語(yǔ)言對(duì)觀察者模式的支持。
(1)Observer接口
這個(gè)接口只定義了一個(gè)方法,即update()方法,當(dāng)被觀察者對(duì)象的狀態(tài)發(fā)生變化時(shí),被觀察者對(duì)象的notifyObservers()方法就會(huì)調(diào)用這一方法。
public interface Observer { void update(Observable o, Object arg); }
(2)Observable類
被觀察者類都是java.util.Observable類的子類。
java.util.Observable提供公開(kāi)的方法支持觀察者對(duì)象,這些方法中有兩個(gè)對(duì)Observable的子類非常重要:一個(gè)是setChanged(),另一個(gè)是notifyObservers()。
第一方法setChanged()被調(diào)用之后會(huì)設(shè)置一個(gè)內(nèi)部標(biāo)記變量,代表被觀察者對(duì)象的狀態(tài)發(fā)生了變化。
第二個(gè)是notifyObservers(),這個(gè)方法被調(diào)用時(shí),會(huì)調(diào)用所有登記過(guò)的觀察者對(duì)象的update()方法,使這些觀察者對(duì)象可以更新自己。
111、使用工廠模式最主要的好處是什么?在哪里使用?
1、工廠模式好處
良好的封裝性、代碼結(jié)構(gòu)清晰;擴(kuò)展性好,如果想增加一個(gè)產(chǎn)品,只需擴(kuò)展一個(gè)工廠類即可;典型的解耦框架;
2、在哪里使用?
需要生成對(duì)象的地方;不同數(shù)據(jù)庫(kù)的訪問(wèn);
112、請(qǐng)解釋自動(dòng)裝配模式的區(qū)別?
有五種自動(dòng)裝配的方式,可以用來(lái)指導(dǎo) Spring 容器用自動(dòng)裝配方式來(lái)進(jìn)行依賴注入。
1、no
默認(rèn)的方式是不進(jìn)行自動(dòng)裝配,通過(guò)顯式設(shè)置 ref 屬性來(lái)進(jìn)行裝配。
2、byName
通過(guò)參數(shù)名 自動(dòng)裝配,Spring 容器在配置文件中發(fā)現(xiàn) bean的 autowire 屬性被設(shè)置成 byname,之后容器試圖匹配、裝配和該 bean 的屬性具有相同名字的 bean。
3、byType:
通過(guò)參數(shù)類型自動(dòng)裝配,Spring 容器在配置文件中發(fā)現(xiàn) bean的 autowire 屬性被設(shè)置成 byType,之后容器試圖匹配、裝配和該 bean 的屬性具有相同類型的 bean。
如果有多個(gè) bean 符合條件,則拋出錯(cuò)誤。
4、constructor
這個(gè)方式類似于 byType, 但是要提供給構(gòu)造器參數(shù),如果沒(méi)有確定的帶參數(shù)的構(gòu)造器參數(shù)類型,將會(huì)拋出異常。
5、autodetect
首先嘗試使用 constructor 來(lái)自動(dòng)裝配,如果無(wú)法工作,則使用 byType 方式。
113、舉一個(gè)用 Java 實(shí)現(xiàn)的裝飾模式(decorator design pattern)?它是作用于對(duì)象層次還是類層次?
- 在Java IO中運(yùn)用了裝飾器模式,inputStream作為抽象類,其下有幾個(gè)實(shí)現(xiàn)類,表示從不同的數(shù)據(jù)源輸入:
- byteArrayInputStreamfileInputStreamStringBufferInputStreamPipedInputStream,從管道產(chǎn)生輸入;
- SequenceInputStream,可將其他流收集合并到一個(gè)流內(nèi);
- FilterInputStream作為裝飾器在JDK中是一個(gè)普通類,其下面有多個(gè)具體裝飾器比如BufferedInputStream、DataInputStream等。
- FilterInputStream內(nèi)部封裝了基礎(chǔ)構(gòu)件:
protected volatile InputStream in;
而B(niǎo)ufferedInputStream在調(diào)用其read()讀取數(shù)據(jù)時(shí)會(huì)委托基礎(chǔ)構(gòu)件來(lái)進(jìn)行更底層的操作,而它自己所起的裝飾作用就是緩沖,在源碼中可以很清楚的看到這一切。
114、什么是 Spring 框架?Spring 框架有哪些主要模塊?
Spring是一個(gè)控制反轉(zhuǎn)和面向切面的容器框架。
Spring有七大功能模塊:
1、Core
Core模塊是Spring的核心類庫(kù),Core實(shí)現(xiàn)了IOC功能。
2、AOP
Apring AOP模塊是Spring的AOP庫(kù),提供了AOP(攔截器)機(jī)制,并提供常見(jiàn)的攔截器,供用戶自定義和配置。
3、orm
提供對(duì)常用ORM框架的管理和支持,hibernate、mybatis等。
4、Dao
Spring提供對(duì)JDBC的支持,對(duì)JDBC進(jìn)行封裝。
5、Web
對(duì)Struts2的支持。
6、Context
Context模塊提供框架式的Bean的訪問(wèn)方式,其它程序可以通過(guò)Context訪問(wèn)Spring的Bean資源,相當(dāng)于資源注入。
7、MVC
MVC模塊為spring提供了一套輕量級(jí)的MVC實(shí)現(xiàn),即Spring MVC。
115、使用 Spring 框架能帶來(lái)哪些好處?
1、輕量級(jí)框架、容器
Spring是一個(gè)容器,管理對(duì)象的生命周期和配置?;谝粋€(gè)可配置原型prototype,你的bean可以使單利的,也可以每次需要時(shí)都生成一個(gè)新的實(shí)例。
2、控制反轉(zhuǎn)IOC
Spring通過(guò)控制反轉(zhuǎn)實(shí)現(xiàn)松耦合。
3、支持AOP
Spring提供對(duì)AOP的支持,它允許將一些通用任務(wù),如安全、事務(wù)、日志等進(jìn)行集中式處理,從而提高了程序的復(fù)用性。
4、輕量級(jí)框架
5、方便測(cè)試
Spring提供Junit4的支持,可以通過(guò)注解方便測(cè)試spring程序。
6、對(duì)Java中很多API進(jìn)行了封裝
7、方便集成各種優(yōu)秀框架
如Struts、hibernate、mybstis。
8、支持聲明式事務(wù)處理
只需通過(guò)配置就可以完成對(duì)事務(wù)的管理,而無(wú)須手動(dòng)編程。
116、Spring IOC、AOP舉例說(shuō)明
1、IOC理論的背景
我們都知道,在采用面向?qū)ο蠓椒ㄔO(shè)計(jì)的軟件系統(tǒng)中,它的底層實(shí)現(xiàn)都是由N個(gè)對(duì)象組成的,所有的對(duì)象通過(guò)彼此的合作,最終實(shí)現(xiàn)系統(tǒng)的業(yè)務(wù)邏輯。
如果我們打開(kāi)機(jī)械式手表的后蓋,就會(huì)看到與上面類似的情形,各個(gè)齒輪分別帶動(dòng)時(shí)針、分針和秒針順時(shí)針旋轉(zhuǎn),從而在表盤上產(chǎn)生正確的時(shí)間。
圖1中描述的就是這樣的一個(gè)齒輪組,它擁有多個(gè)獨(dú)立的齒輪,這些齒輪相互嚙合在一起,協(xié)同工作,共同完成某項(xiàng)任務(wù)。我們可以看到,在這樣的齒輪組中,如果有一個(gè)齒輪出了問(wèn)題,就可能會(huì)影響到整個(gè)齒輪組的正常運(yùn)轉(zhuǎn)。
齒輪組中齒輪之間的嚙合關(guān)系,與軟件系統(tǒng)中對(duì)象之間的耦合關(guān)系非常相似。
對(duì)象之間的耦合關(guān)系是無(wú)法避免的,也是必要的,這是協(xié)同工作的基礎(chǔ)?,F(xiàn)在,伴隨著工業(yè)級(jí)應(yīng)用的規(guī)模越來(lái)越龐大,對(duì)象之間的依賴關(guān)系也越來(lái)越復(fù)雜,經(jīng)常會(huì)出現(xiàn)對(duì)象之間的多重依賴性關(guān)系
因此,架構(gòu)師和設(shè)計(jì)師對(duì)于系統(tǒng)的分析和設(shè)計(jì),將面臨更大的挑戰(zhàn)。對(duì)象之間耦合度過(guò)高的系統(tǒng),必然會(huì)出現(xiàn)牽一發(fā)而動(dòng)全身的情形。
耦合關(guān)系不僅會(huì)出現(xiàn)在對(duì)象與對(duì)象之間,也會(huì)出現(xiàn)在軟件系統(tǒng)的各模塊之間,以及軟件系統(tǒng)和硬件系統(tǒng)之間。如何降低系統(tǒng)之間、模塊之間和對(duì)象之間的耦合度,是軟件工程永遠(yuǎn)追求的目標(biāo)之一。
為了解決對(duì)象之間的耦合度過(guò)高的問(wèn)題,軟件專家Michael Mattson提出了IOC理論,用來(lái)實(shí)現(xiàn)對(duì)象之間的“解耦”,目前這個(gè)理論已經(jīng)被成功地應(yīng)用到實(shí)踐當(dāng)中,很多的J2EE項(xiàng)目均采用了IOC框架產(chǎn)品Spring。
2、什么是控制反轉(zhuǎn)
IOC是Inversion of Control的縮寫,多數(shù)書籍翻譯成“控制反轉(zhuǎn)”,還有些書籍翻譯成為“控制反向”或者“控制倒置”。
1996年,Michael Mattson在一篇有關(guān)探討面向?qū)ο罂蚣艿奈恼轮?,首先提出了IOC 這個(gè)概念。
對(duì)于面向?qū)ο笤O(shè)計(jì)及編程的基本思想,前面我們已經(jīng)講了很多了,不再贅述,簡(jiǎn)單來(lái)說(shuō)就是把復(fù)雜系統(tǒng)分解成相互合作的對(duì)象,這些對(duì)象類通過(guò)封裝以后,內(nèi)部實(shí)現(xiàn)對(duì)外部是透明的,從而降低了解決問(wèn)題的復(fù)雜度,而且可以靈活地被重用和擴(kuò)展。
IOC理論提出的觀點(diǎn)大體是這樣的:借助于“第三方”實(shí)現(xiàn)具有依賴關(guān)系的對(duì)象之間的解耦,如下圖:
大家看到了吧,由于引進(jìn)了中間位置的“第三方”,也就是IOC容器,使得A、B、C、D這4個(gè)對(duì)象沒(méi)有了耦合關(guān)系,齒輪之間的傳動(dòng)全部依靠“第三方”了,全部對(duì)象的控制權(quán)全部上繳給“第三方”IOC容器,所以,IOC容器成了整個(gè)系統(tǒng)的關(guān)鍵核心,它起到了一種類似“粘合劑”的作用,把系統(tǒng)中的所有對(duì)象粘合在一起發(fā)揮作用,如果沒(méi)有這個(gè)“粘合劑”,對(duì)象與對(duì)象之間會(huì)彼此失去聯(lián)系,這就是有人把IOC容器比喻成“粘合劑”的由來(lái)。
我們?cè)賮?lái)做個(gè)試驗(yàn):把上圖中間的IOC容器拿掉,然后再來(lái)看看這套系統(tǒng)(拿掉IoC容器后的系統(tǒng)):
我們現(xiàn)在看到的畫面,就是我們要實(shí)現(xiàn)整個(gè)系統(tǒng)所需要完成的全部?jī)?nèi)容。
這時(shí)候,A、B、C、D這4個(gè)對(duì)象之間已經(jīng)沒(méi)有了耦合關(guān)系,彼此毫無(wú)聯(lián)系,這樣的話,當(dāng)你在實(shí)現(xiàn)A的時(shí)候,根本無(wú)須再去考慮B、C和D了,對(duì)象之間的依賴關(guān)系已經(jīng)降低到了最低程度。
所以,如果真能實(shí)現(xiàn)IOC容器,對(duì)于系統(tǒng)開(kāi)發(fā)而言,這將是一件多么美好的事情,參與開(kāi)發(fā)的每一成員只要實(shí)現(xiàn)自己的類就可以了,跟別人沒(méi)有任何關(guān)系!
我們?cè)賮?lái)看看,控制反轉(zhuǎn)(IOC)到底為什么要起這么個(gè)名字?我們來(lái)對(duì)比一下:
軟件系統(tǒng)在沒(méi)有引入IOC容器之前,如圖1所示,對(duì)象A依賴于對(duì)象B,那么對(duì)象A在初始化或者運(yùn)行到某一點(diǎn)的時(shí)候,自己必須主動(dòng)去創(chuàng)建對(duì)象B或者使用已經(jīng)創(chuàng)建的對(duì)象B。
無(wú)論是創(chuàng)建還是使用對(duì)象B,控制權(quán)都在自己手上。
軟件系統(tǒng)在引入IOC容器之后,這種情形就完全改變了,如圖3所示,由于IOC容器的加入,對(duì)象A與對(duì)象B之間失去了直接聯(lián)系
所以,當(dāng)對(duì)象A運(yùn)行到需要對(duì)象B的時(shí)候,IOC容器會(huì)主動(dòng)創(chuàng)建一個(gè)對(duì)象B注入到對(duì)象A需要的地方。
通過(guò)前后的對(duì)比,我們不難看出來(lái):對(duì)象A獲得依賴對(duì)象B的過(guò)程,由主動(dòng)行為變?yōu)榱吮粍?dòng)行為,控制權(quán)顛倒過(guò)來(lái)了,這就是“控制反轉(zhuǎn)”這個(gè)名稱的由來(lái)。
3、IOC的別名:依賴注入(DI)
2004年,Martin Fowler探討了同一個(gè)問(wèn)題,既然IOC是控制反轉(zhuǎn),那么到底是“哪些方面的控制被反轉(zhuǎn)了呢?”
經(jīng)過(guò)詳細(xì)地分析和論證后,他得出了答案:“獲得依賴對(duì)象的過(guò)程被反轉(zhuǎn)了”。
控制被反轉(zhuǎn)之后,獲得依賴對(duì)象的過(guò)程由自身管理變?yōu)榱擞蒊OC容器主動(dòng)注入。
于是,他給“控制反轉(zhuǎn)”取了一個(gè)更合適的名字叫做“依賴注入(Dependency Injection)”。
他的這個(gè)答案,實(shí)際上給出了實(shí)現(xiàn)IOC的方法:注入。
所謂依賴注入,就是由IOC容器在運(yùn)行期間,動(dòng)態(tài)地將某種依賴關(guān)系注入到對(duì)象之中。
所以,依賴注入(DI)和控制反轉(zhuǎn)(IOC)是從不同的角度的描述的同一件事情,就是指通過(guò)引入IOC容器,利用依賴關(guān)系注入的方式,實(shí)現(xiàn)對(duì)象之間的解耦。
我們舉一個(gè)生活中的例子,來(lái)幫助理解依賴注入的過(guò)程。
大家對(duì)USB接口和USB設(shè)備應(yīng)該都很熟悉吧,USB為我們使用電腦提供了很大的方便,現(xiàn)在有很多的外部設(shè)備都支持USB接口。
現(xiàn)在,我們利用電腦主機(jī)和USB接口來(lái)實(shí)現(xiàn)一個(gè)任務(wù):從外部USB設(shè)備讀取一個(gè)文件。
電腦主機(jī)讀取文件的時(shí)候,它一點(diǎn)也不會(huì)關(guān)心USB接口上連接的是什么外部設(shè)備,而且它確實(shí)也無(wú)須知道。
它的任務(wù)就是讀取USB接口,掛接的外部設(shè)備只要符合USB接口標(biāo)準(zhǔn)即可。所以,如果我給電腦主機(jī)連接上一個(gè)U盤,那么主機(jī)就從U盤上讀取文件;
如果我給電腦主機(jī)連接上一個(gè)外置硬盤,那么電腦主機(jī)就從外置硬盤上讀取文件。
掛接外部設(shè)備的權(quán)力由我作主,即控制權(quán)歸我,至于USB接口掛接的是什么設(shè)備,電腦主機(jī)是決定不了,它只能被動(dòng)的接受。
電腦主機(jī)需要外部設(shè)備的時(shí)候,根本不用它告訴我,我就會(huì)主動(dòng)幫它掛上它想要的外部設(shè)備,你看我的 服務(wù)是多么的到位。這就是我們生活中常見(jiàn)的一個(gè)依賴注入的例子。
在這個(gè)過(guò)程中,我就起到了IOC容器的作用。
通過(guò)這個(gè)例子,依賴注入的思路已經(jīng)非常清楚:當(dāng)電腦主機(jī)讀取文件的時(shí)候,我就把它所要依賴的外部設(shè)備,幫他掛接上。整個(gè)外部設(shè)備注入的過(guò)程和一個(gè)被依賴的對(duì)象在系統(tǒng)運(yùn)行時(shí)被注入另外一個(gè)對(duì)象內(nèi)部的過(guò)程完全一樣。
我們把依賴注入應(yīng)用到軟件系統(tǒng)中,再來(lái)描述一下這個(gè)過(guò)程:
對(duì)象A依賴于對(duì)象B,當(dāng)對(duì)象 A需要用到對(duì)象B的時(shí)候,IOC容器就會(huì)立即創(chuàng)建一個(gè)對(duì)象B送給對(duì)象A。
IOC容器就是一個(gè)對(duì)象制造工廠,你需要什么,它會(huì)給你送去,你直接使用就行了,而再也不用去關(guān)心你所用的東西是如何制成的,也不用關(guān)心最后是怎么被銷毀的,這一切全部由IOC容器包辦。
在傳統(tǒng)的實(shí)現(xiàn)中,由程序內(nèi)部代碼來(lái)控制組件之間的關(guān)系。
我們經(jīng)常使用new關(guān)鍵字來(lái)實(shí)現(xiàn)兩個(gè)組件之間關(guān)系的組合,這種實(shí)現(xiàn)方式會(huì)造成組件之間耦合。
IOC很好地解決了該問(wèn)題,它將實(shí)現(xiàn)組件間關(guān)系從程序內(nèi)部提到外部容器,也就是說(shuō)由容器在運(yùn)行期將組件間的某種依賴關(guān)系動(dòng)態(tài)注入組件中。
4、IOC為我們帶來(lái)了什么好處
我們還是從USB的例子說(shuō)起,使用USB外部設(shè)備比使用內(nèi)置硬盤,到底帶來(lái)什么好處?
第一、USB設(shè)備作為電腦主機(jī)的外部設(shè)備,在插入主機(jī)之前,與電腦主機(jī)沒(méi)有任何的關(guān)系,只有被我們連接在一起之后,兩者才發(fā)生聯(lián)系,具有相關(guān)性。
所以,無(wú)論兩者中的任何一方出現(xiàn)什么的問(wèn)題,都不會(huì)影響另一方的運(yùn)行。
這種特性體現(xiàn)在軟件工程中,就是可維護(hù)性比較好,非常便于進(jìn)行單元測(cè)試,便于調(diào)試程序和診斷故障。
代碼中的每一個(gè)Class都可以單獨(dú)測(cè)試,彼此之間互不影響,只要保證自身的功能無(wú)誤即可,這就是組件之間低耦合或者無(wú)耦合帶來(lái)的好處。
第二、USB設(shè)備和電腦主機(jī)的之間無(wú)關(guān)性,還帶來(lái)了另外一個(gè)好處,生產(chǎn)USB設(shè)備的廠商和生產(chǎn)電腦主機(jī)的廠商完全可以是互不相干的人,各干各事,他們之間唯一需要遵守的就是USB接口標(biāo)準(zhǔn)。
這種特性體現(xiàn)在軟件開(kāi)發(fā)過(guò)程中,好處可是太大了。
每個(gè)開(kāi)發(fā)團(tuán)隊(duì)的成員都只需要關(guān)心實(shí)現(xiàn)自身的業(yè)務(wù)邏輯,完全不用去關(guān)心其它的人工作進(jìn)展,因?yàn)槟愕娜蝿?wù)跟別人沒(méi)有任何關(guān)系,你的任務(wù)可以單獨(dú)測(cè)試,你的任務(wù)也不用依賴于別人的組件,再也不用扯不清責(zé)任了。
所以,在一個(gè)大中型項(xiàng)目中,團(tuán)隊(duì)成員分工明確、責(zé)任明晰,很容易將一個(gè)大的任務(wù)劃分為細(xì)小的任務(wù),開(kāi)發(fā)效率和產(chǎn)品質(zhì)量必將得到大幅度的提高。
第三、同一個(gè)USB外部設(shè)備可以插接到任何支持USB的設(shè)備,可以插接到電腦主機(jī),也可以插接到DV機(jī),USB外部設(shè)備可以被反復(fù)利用。在軟件工程中,這種特性就是可復(fù)用性好,我們可以把具有普遍性的常用組件獨(dú)立出來(lái),反復(fù)利用到項(xiàng)目中的其它部分,或者是其它項(xiàng)目,當(dāng)然這也是面向?qū)ο蟮幕咎卣鳌?/p>
顯然,IOC不僅更好地貫徹了這個(gè)原則,提高了模塊的可復(fù)用性。符合接口標(biāo)準(zhǔn)的實(shí)現(xiàn),都可以插接到支持此標(biāo)準(zhǔn)的模塊中。
第四、同USB外部設(shè)備一樣,模塊具有熱插拔特性。IOC生成對(duì)象的方式轉(zhuǎn)為外置方式,也就是把對(duì)象生成放在配置文件里進(jìn)行定義,這樣,當(dāng)我們更換一個(gè)實(shí)現(xiàn)子類將會(huì)變得很簡(jiǎn)單,只要修改配置文件就可以了,完全具有熱插撥的特性。
以上幾點(diǎn)好處,難道還不足以打動(dòng)我們,讓我們?cè)陧?xiàng)目開(kāi)發(fā)過(guò)程中使用IOC框架嗎?
5、IOC容器的技術(shù)剖析
IOC中最基本的技術(shù)就是“反射(Reflection)”編程,目前.Net C#、Java和PHP5等語(yǔ)言均支持,其中PHP5的技術(shù)書籍中,有時(shí)候也被翻譯成“映射”。有關(guān)反射的概念和用法,大家應(yīng)該都很清楚,通俗來(lái)講就是根據(jù)給出的類名(字符串方式)來(lái)動(dòng)態(tài)地生成對(duì)象。
這種編程方式可以讓對(duì)象在生成時(shí)才決定到底是哪一種對(duì)象。
反射的應(yīng)用是很廣泛的,很多的成熟的框架,比如象Java中的Hibernate、Spring框架,.Net中 NHibernate、Spring.Net框架都是把“反射”做為最基本的技術(shù)手段。
反射技術(shù)其實(shí)很早就出現(xiàn)了,但一直被忽略,沒(méi)有被進(jìn)一步的利用。
當(dāng)時(shí)的反射編程方式相對(duì)于正常的對(duì)象生成方式要慢至少得10倍。
現(xiàn)在的反射技術(shù)經(jīng)過(guò)改良優(yōu)化,已經(jīng)非常成熟,反射方式生成對(duì)象和通常對(duì)象生成方式,速度已經(jīng)相差不大了,大約為1-2倍的差距。
我們可以把IOC容器的工作模式看做是工廠模式的升華,可以把IOC容器看作是一個(gè)工廠,這個(gè)工廠里要生產(chǎn)的對(duì)象都在配置文件中給出定義,然后利用編程語(yǔ)言的的反射編程,根據(jù)配置文件中給出的類名生成相應(yīng)的對(duì)象。
從實(shí)現(xiàn)來(lái)看,IOC是把以前在工廠方法里寫死的對(duì)象生成代碼,改變?yōu)橛膳渲梦募?lái)定義,也就是把工廠和對(duì)象生成這兩者獨(dú)立分隔開(kāi)來(lái),目的就是提高靈活性和可維護(hù)性。
6、IOC容器的一些產(chǎn)品
Sun ONE技術(shù)體系下的IOC容器有:輕量級(jí)的有Spring、Guice、Pico Container、Avalon、HiveMind;
重量級(jí)的有EJB;
不輕不重的有JBoss,Jdon等等。
Spring框架作為Java開(kāi)發(fā)中SSH(Struts、Spring、Hibernate)三劍客之一,大中小項(xiàng)目中都有使用,非常成熟,應(yīng)用廣泛,EJB在關(guān)鍵性的工業(yè)級(jí)項(xiàng)目中也被使用,比如某些電信業(yè)務(wù)。
Net技術(shù)體系下的IOC容器有:Spring.Net、Castle等等。
Spring.Net是從Java的Spring移植過(guò)來(lái)的IOC容器,Castle的IOC容器就是Windsor部分。
它們均是輕量級(jí)的框架,比較成熟,其中Spring.Net已經(jīng)被逐漸應(yīng)用于各種項(xiàng)目中。
7、使用IOC框架應(yīng)該注意什么
使用IOC框架產(chǎn)品能夠給我們的開(kāi)發(fā)過(guò)程帶來(lái)很大的好處,但是也要充分認(rèn)識(shí)引入IOC框架的缺點(diǎn),做到心中有數(shù),杜絕濫用框架。
(1)軟件系統(tǒng)中由于引入了第三方IOC容器,生成對(duì)象的步驟變得有些復(fù)雜,本來(lái)是兩者之間的事情,又憑空多出一道手續(xù)
所以,我們?cè)趧傞_(kāi)始使用IOC框架的時(shí)候,會(huì)感覺(jué)系統(tǒng)變得不太直觀。所以,引入了一個(gè)全新的框架,就會(huì)增加團(tuán)隊(duì)成員學(xué)習(xí)和認(rèn)識(shí)的培訓(xùn)成本,并且在以后的運(yùn)行維護(hù)中,還得讓新加入者具備同樣的知識(shí)體系。
(2)由于IOC容器生成對(duì)象是通過(guò)反射方式,在運(yùn)行效率上有一定的損耗。如果你要追求運(yùn)行效率的話,就必須對(duì)此進(jìn)行權(quán)衡。
(3)、具體到IOC框架產(chǎn)品(比如:Spring)來(lái)講,需要進(jìn)行大量的配制工作,比較繁瑣,對(duì)于一些小的項(xiàng)目而言,客觀上也可能加大一些工作成本。
(4)IOC框架產(chǎn)品本身的成熟度需要進(jìn)行評(píng)估,如果引入一個(gè)不成熟的IOC框架產(chǎn)品,那么會(huì)影響到整個(gè)項(xiàng)目,所以這也是一個(gè)隱性的風(fēng)險(xiǎn)。
我們大體可以得出這樣的結(jié)論:一些工作量不大的項(xiàng)目或者產(chǎn)品,不太適合使用IOC框架產(chǎn)品。另外,如果團(tuán)隊(duì)成員的知識(shí)能力欠缺,對(duì)于IOC框架產(chǎn)品缺乏深入的理解,也不要貿(mào)然引入。
最后,特別強(qiáng)調(diào)運(yùn)行效率的項(xiàng)目或者產(chǎn)品,也不太適合引入IOC框架產(chǎn)品,象WEB2.0網(wǎng)站就是這種情況。
117、什么是控制反轉(zhuǎn)(IOC)?什么是依賴注入?
借助Spring實(shí)現(xiàn)具有依賴關(guān)系的對(duì)象之間的解耦。
對(duì)象A運(yùn)行需要對(duì)象B,由主動(dòng)創(chuàng)建變?yōu)镮OC容器注入,這便是控制反轉(zhuǎn)。
獲得依賴對(duì)象的過(guò)程被反轉(zhuǎn)了,獲取依賴對(duì)象的過(guò)程由自身創(chuàng)建變?yōu)橛蒊OC容器注入,這便是依賴注入。
118、BeanFactory 和 ApplicationContext 有什么區(qū)別?
1、BeanFactory是Spring的最底層接口,包含bean的定義,管理bean的加載,實(shí)例化,控制bean的生命周期,特點(diǎn)是每次獲取對(duì)象時(shí)才會(huì)創(chuàng)建對(duì)象。
ApplicationContext是BeanFactory的子接口,擁有BeanFactory的全部功能,并且擴(kuò)展了很多高級(jí)特性,每次容器啟動(dòng)時(shí)就會(huì)創(chuàng)建所有的對(duì)象。
- ApplicationContext的額外功能:繼承MessageSource,支持國(guó)際化;
- 統(tǒng)一的資源文件訪問(wèn)方式;
- 提供在監(jiān)聽(tīng)器中注冊(cè)bean;
- 同時(shí)加載過(guò)個(gè)配置文件;
- 載入多個(gè)(有繼承關(guān)系)上下文,使得每個(gè)上下文都專注于一個(gè)特定的層次,比如應(yīng)用的web層;
2、BeanFactory通常以編程的方式被創(chuàng)建,ApplicationContext可以以聲明的方式創(chuàng)建,如使用ContextLoader。
3、BeanFactory 和 ApplicationContext都支持BeanPostProcessor,BeanFactoryPostProcessor,但BeanFactory需要手動(dòng)注冊(cè),ApplicationContext則是自動(dòng)注冊(cè)。
119、什么是 JavaConfig?
JavaConfig是Spring3.0新增的概念,就是以注解的形式取代Spring中繁瑣的xml文件。
JavaConfig結(jié)合了xml的解耦和java編譯時(shí)檢查的優(yōu)點(diǎn)。
- @Configuration,表示這個(gè)類是配置類;
- @ComponentScan,相當(dāng)于xml的<context:componentScan basepackage=>;
- @Bean,相當(dāng)于xml的<bean id="student" class="com.guor.entity">;
- @EnableWebMvc,相當(dāng)于xml的<mvc:annotation-driven>;
- @ImportResource,相當(dāng)于xml的<import resource="application-context-cache.xml">;
- @PropertySource,用于讀取properties配置文件;
- @Profile,一般用于多環(huán)境配置,激活時(shí)可用
- @ActiveProfile("dev")注解;
120、什么是 ORM 框架?
ORM(Object-relational mapping),對(duì)象關(guān)系映射。
是為了解決面向?qū)ο笈c關(guān)系型數(shù)據(jù)庫(kù)存在的不匹配問(wèn)題。
ORM框架的優(yōu)點(diǎn):
- 開(kāi)發(fā)效率更高
- 數(shù)據(jù)訪問(wèn)更抽象、
- 輕便支持面向?qū)ο蠓庋b
121、Spring 有幾種配置方式?
1、xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="jackma" class="com.tyq.dto.User"> <property name="name" value="jackma" /> <property name="age" value="55" /> <property name="dog" ref="jm" /> </bean> <bean id="jm" class="com.tyq.dto.Dog"> <property name="name" value="jack" /> <property name="breed" value="金毛" /> <property name="age" value="2" /> </bean> </beans>
2、基于注解的方式
項(xiàng)目越來(lái)越大,基于xml配置太麻煩,Spring 2.x時(shí)代提供了聲明bean的注解。
(1)Bean的定義
@Component、@Controller、@Service、@Repository。
(2)Bean的注入
@Autowire
3、基于Java的方式
Spring 3.x以后,可以通過(guò)Java代碼裝配Bean。
@Configuration public class DemoConfig { @Bean public User zs(){ return new User(); } @Bean public Dog dog(){ return new Dog(); } @Bean //兩個(gè)狗 public Dog haqi(){ return new Dog(); } }
@Component("zs") public class User { private String name; private int age; private Dog dog; //get,set方法略 }
原來(lái)就是配置類啊,通過(guò)@Bean、@Component、getBean方式進(jìn)行Bean的注冊(cè)和發(fā)現(xiàn)。
122、請(qǐng)解釋 Spring Bean 的生命周期?
- 通過(guò)構(gòu)造器或工廠方法創(chuàng)建bean實(shí)例;
- 為bean的屬性賦值;
- 調(diào)用bean的初始化方法;
- 使用bean;
- 當(dāng)容器關(guān)閉時(shí),調(diào)用bean的銷毀方法;
123、Spring Bean 的作用域之間有什么區(qū)別?
Spring容器中的bean可以分為5個(gè)范圍:
- singleton:這種bean范圍是默認(rèn)的,這種范圍確保不管接受多少請(qǐng)求,每個(gè)容器中只喲一個(gè)bean的實(shí)例,單例模式;
- prototype:為每一個(gè)bean提供一個(gè)實(shí)例;
- request:在請(qǐng)求bean范圍內(nèi)為每一個(gè)來(lái)自客戶端的網(wǎng)絡(luò)請(qǐng)求創(chuàng)建一個(gè)實(shí)例,在請(qǐng)求完畢后,bean會(huì)失效并被垃圾回收器回收;
- session:為每個(gè)session創(chuàng)建一個(gè)實(shí)例,session過(guò)期后,bean會(huì)隨之消失;
- global-session:global-session和Portlet應(yīng)用相關(guān)。當(dāng)你的應(yīng)用部署在Portlet容器中工作時(shí),它包含很多portlet。如果你想要聲明讓所有的portlet公用全局的存儲(chǔ)變量的話,那么全局變量需要存儲(chǔ)在global-session中。
124、如何在 Spring Boot 中禁用 Actuator 端點(diǎn)安全性?
默認(rèn)情況下,所有敏感的HTTP端點(diǎn)都是安全的,只有具有Actuator角色的用戶才能訪問(wèn)它們。
安全性是使用標(biāo)準(zhǔn)的HTTPServletRequest.isUserInRole方法實(shí)施的。
我們可以使用management.security.enable = false來(lái)禁用安全性。
只有在執(zhí)行機(jī)構(gòu)端點(diǎn)在防火墻后訪問(wèn)時(shí),才建議禁用安全性。
125、什么是 Spring inner beans?
在Spring框架中,無(wú)論何時(shí)bean被使用時(shí),當(dāng)僅被調(diào)用一個(gè)屬性。
可以將這個(gè)bean聲明為內(nèi)部bean。
內(nèi)部bean可以用setter注入“屬性”和構(gòu)造方法注入“構(gòu)造參數(shù)”的方式來(lái)實(shí)現(xiàn)。比如,在我們的應(yīng)用程序中,一個(gè)Customer類引用了一個(gè)Person類,我們要做的是創(chuàng)建一個(gè)Person實(shí)例,然后再Customer內(nèi)部使用。
package com; public class Customer { private Person person; } class Person{ private int id; private String name; private int age; }
<bean id="CustomerBean" class="com.Customer"> <property name="person"> <bean class="com.person"> <property name="id" value=1 /> <property name="name" value="素小暖" /> <property name="age" value=18 /> </bean> </property> </bean>
到此這篇關(guān)于Java經(jīng)典面試題最全匯總208道(三)的文章就介紹到這了,更多相關(guān)Java面試題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot分頁(yè)查詢功能的實(shí)現(xiàn)方法
在實(shí)際的項(xiàng)目開(kāi)發(fā)過(guò)程中,分頁(yè)顯示是很常見(jiàn)的頁(yè)面布局,所以學(xué)習(xí)如何實(shí)現(xiàn)分頁(yè)也是必要的,下面這篇文章主要給大家介紹了關(guān)于SpringBoot分頁(yè)查詢功能的實(shí)現(xiàn)方法,需要的朋友可以參考下2022-06-06SpringBoot集成EasyExcel實(shí)現(xiàn)Excel導(dǎo)入的方法
這篇文章主要介紹了SpringBoot集成EasyExcel實(shí)現(xiàn)Excel導(dǎo)入的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01SpringBoot結(jié)合Neo4j自定義cypherSql的方法
這篇文章主要介紹了SpringBoot結(jié)合Neo4j自定義cypherSql,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-11-11RocketMQ消息生產(chǎn)者是如何選擇Broker示例詳解
這篇文章主要為大家介紹了RocketMQ消息生產(chǎn)者是如何選擇Broker示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Java實(shí)現(xiàn)復(fù)制文件并命名的超簡(jiǎn)潔寫法
這篇文章主要介紹了Java實(shí)現(xiàn)復(fù)制文件并命名的超簡(jiǎn)潔寫法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11