2019java 开发工程师 最新面试官 问的问题
1.Java中的io流面試題
答案:我給你打個(gè)比方你就明白了;比如你家的水龍頭的管道就是一個(gè)流:流又分為輸入輸出流,輸入流就是你家水龍頭抽水庫(kù)水的那頭,輸出流就是你家水龍頭流到你家大水缸的那頭。現(xiàn)在有個(gè)A.txt文件,你要讀取里面的信息,就相當(dāng)于水龍頭抽水庫(kù)水,然后讀取完后寫(xiě)入到另一個(gè)文件里面,就是相當(dāng)于水龍頭抽到水后流到大水缸。很簡(jiǎn)單吧,就是一進(jìn)一出的事,沒(méi)這么復(fù)雜
1.1: 以流向來(lái)劃分(針對(duì)內(nèi)存):A.輸入流:文件—>內(nèi)存??? 讀文件B.輸出流:內(nèi)存—>文件??? 寫(xiě)文件2)從內(nèi)容劃分A.字節(jié)流:以8位的形式來(lái)處理,不能輸出漢字B.字符流:在字節(jié)流上進(jìn)行包裝得到的,可以處理字節(jié)流,也可以處理漢字??? 注:在最底層,所有的I/O操作都是字節(jié)流的形式,字符流是為了處理漢字方便,字節(jié)流的處理速度快?
答: 字節(jié)流是按字節(jié)讀取或?qū)懭朐O(shè)備,但字符流是以字符為單位讀取或?qū)懭朐O(shè)備。
如果是二進(jìn)制文件,需要用字節(jié)流讀取。一般來(lái)說(shuō),字符流只處理文本文件。在設(shè)備中,大多數(shù)情況是以字節(jié)形式存儲(chǔ)數(shù)據(jù)的,因此字符流通過(guò)需要傳入字節(jié)流當(dāng)參數(shù)。
原文是這樣的意思,用BufferedReader封裝一個(gè)InputStream,再用DataInputStream封裝這個(gè)InputStream,這樣做之后,先用BufferedReader從流中讀取一行,然后分別用這個(gè)InputStream讀取一個(gè)字符和DataInputStream讀取一行,再用BufferedReader讀取一行,結(jié)果BufferedReader均能讀到數(shù)據(jù),而InputStream和DataInputStream均讀不到數(shù)據(jù).數(shù)據(jù)流中只有40多個(gè)字符。這說(shuō)明了,BufferedReader第一次讀取時(shí),就把這40多個(gè)字符都讀取出來(lái),緩沖起來(lái)了,后面每次讀的時(shí)候,都只是從緩沖里拿出來(lái)。40多個(gè)字符就一次被BufferedReader讀進(jìn)去緩存起來(lái)了,所以InputStream和DataInputStream就都讀不到字符了。?
原文并猜想,如果流中的數(shù)據(jù)夠多到BufferedReader緩存不下來(lái)的時(shí)候,InputStream和DataInputStream就能讀到數(shù)據(jù)了。?
注解:緩沖流分為字節(jié)和字符緩沖流
字節(jié)緩沖流為:
BufferedInputStream—字節(jié)輸入緩沖流
BufferedOutputStream—字節(jié)輸出緩沖流
字符緩沖流為:
BufferedReader—字符輸入緩沖流
BufferedWriter—字符輸出緩沖流
下面主要介紹這四種緩沖流的使用。
?
2.多線程面試問(wèn)題
?
?
答:程序的一次執(zhí)行就可以看作是一個(gè)進(jìn)程。進(jìn)程中又包含了許多的線程,進(jìn)程之間的內(nèi)存不可以共享,線程之間共享進(jìn)程的內(nèi)存。
一、繼承Thread類(lèi)創(chuàng)建線程類(lèi)
(1)定義Thread類(lèi)的子類(lèi),并重寫(xiě)該類(lèi)的run方法,該run方法的方法體就代表了線程要完成的任務(wù)。因此把run()方法稱(chēng)為執(zhí)行體。
(2)創(chuàng)建Thread子類(lèi)的實(shí)例,即創(chuàng)建了線程對(duì)象。
(3)調(diào)用線程對(duì)象的start()方法來(lái)啟動(dòng)該線程。
二、通過(guò)Runnable接口創(chuàng)建線程類(lèi)
(1)定義runnable接口的實(shí)現(xiàn)類(lèi),并重寫(xiě)該接口的run()方法,該run()方法的方法體同樣是該線程的線程執(zhí)行體。
(2)創(chuàng)建 Runnable實(shí)現(xiàn)類(lèi)的實(shí)例,并依此實(shí)例作為Thread的target來(lái)創(chuàng)建Thread對(duì)象,該Thread對(duì)象才是真正的線程對(duì)象。
(3)調(diào)用線程對(duì)象的start()方法來(lái)啟動(dòng)該線程。
三、通過(guò)Callable和Future創(chuàng)建線程
(1)創(chuàng)建Callable接口的實(shí)現(xiàn)類(lèi),并實(shí)現(xiàn)call()方法,該call()方法將作為線程執(zhí)行體,并且有返回值。
(2)創(chuàng)建Callable實(shí)現(xiàn)類(lèi)的實(shí)例,使用FutureTask類(lèi)來(lái)包裝Callable對(duì)象,該FutureTask對(duì)象封裝了該Callable對(duì)象的call()方法的返回值。
(3)使用FutureTask對(duì)象作為Thread對(duì)象的target創(chuàng)建并啟動(dòng)新線程。
(4)調(diào)用FutureTask對(duì)象的get()方法來(lái)獲得子線程執(zhí)行結(jié)束后的返回值
二、創(chuàng)建線程的三種方式的對(duì)比
采用實(shí)現(xiàn)Runnable、Callable接口的方式創(chuàng)見(jiàn)多線程時(shí),優(yōu)勢(shì)是:
線程類(lèi)只是實(shí)現(xiàn)了Runnable接口或Callable接口,還可以繼承其他類(lèi)。
在這種方式下,多個(gè)線程可以共享同一個(gè)target對(duì)象,所以非常適合多個(gè)相同線程來(lái)處理同一份資源的情況,從而可以將CPU、代碼和數(shù)據(jù)分開(kāi),形成清晰的模型,較好地體現(xiàn)了面向?qū)ο蟮乃枷搿?/span>
劣勢(shì)是:
編程稍微復(fù)雜,如果要訪問(wèn)當(dāng)前線程,則必須使用Thread.currentThread()方法。
使用繼承Thread類(lèi)的方式創(chuàng)建多線程時(shí)優(yōu)勢(shì)是:
編寫(xiě)簡(jiǎn)單,如果需要訪問(wèn)當(dāng)前線程,則無(wú)需使用Thread.currentThread()方法,直接使用this即可獲得當(dāng)前線程。
劣勢(shì)是:
線程類(lèi)已經(jīng)繼承了Thread類(lèi),所以不能再繼承其他父類(lèi)。
?
答:樂(lè)觀鎖適用于多讀的應(yīng)用類(lèi)型,這樣可以提高吞吐量,像數(shù)據(jù)庫(kù)如果提供類(lèi)似于write_condition機(jī)智的其實(shí)都是提供的樂(lè)觀鎖。 相反,如果經(jīng)常發(fā)生沖突,上層應(yīng)用會(huì)不斷進(jìn)行 retry,這樣反而降低了性能,所以這種情況下用悲觀鎖比較合適
1.start() 啟動(dòng)線程并執(zhí)行相應(yīng)的run()方法 ---run() 子線程要執(zhí)行的代碼放入run()方法。
2.getName() 獲取此線程的名字?setName() 設(shè)置
此線程的名字。
3.join() 執(zhí)行調(diào)用join()方法線程),阻斷其他線程。
4.sleep(毫秒)休眠。
?
線程安全的理解?
答 :線程安全就是多線程訪問(wèn)時(shí),采用了加鎖機(jī)制,當(dāng)一個(gè)線程訪問(wèn)該類(lèi)的某個(gè)數(shù)據(jù)時(shí),進(jìn)行保護(hù),其他線程不能進(jìn)行訪問(wèn)直到該線程讀取完,其他線程才可使用
答:對(duì)于sleep()方法,我們首先要知道該方法是屬于Thread類(lèi)中的。而wait()方法,則是屬于Object類(lèi)中的。
sleep()方法導(dǎo)致了程序暫停執(zhí)行指定的時(shí)間,讓出cpu該其他線程,但是他的監(jiān)控狀態(tài)依然保持者,當(dāng)指定的時(shí)間到了又會(huì)自動(dòng)恢復(fù)運(yùn)行狀態(tài)。
在調(diào)用sleep()方法的過(guò)程中,線程不會(huì)釋放對(duì)象鎖。
而當(dāng)調(diào)用wait()方法的時(shí)候,線程會(huì)放棄對(duì)象鎖,進(jìn)入等待此對(duì)象的等待鎖定池,只有針對(duì)此對(duì)象調(diào)用notify()方法后本線程才進(jìn)入對(duì)象鎖定池準(zhǔn)備
?
3.集合面試問(wèn)題(HashMap居多,問(wèn)的也有上機(jī)也有)
??1、繼承的父類(lèi)不同
? ? ??Hashtable繼承自Dictionary類(lèi),而HashMap繼承自AbstractMap類(lèi)。但二者都實(shí)現(xiàn)了Map接口。
?2、線程安全性不同
? ? ??javadoc中關(guān)于hashmap的一段描述如下:此實(shí)現(xiàn)不是同步的。如果多個(gè)線程同時(shí)訪問(wèn)一個(gè)哈希映射,而其中至少一個(gè)線程從結(jié)構(gòu)上修改了該映射,則它必須保持外部同步。
?
? ? ??Hashtable 中的方法是Synchronize的,而HashMap中的方法在缺省情況下是非Synchronize的。在多線程并發(fā)的環(huán)境下,可以直接使用Hashtable,不需要自己為它的方法實(shí)現(xiàn)同步,但使用HashMap時(shí)就必須要自己增加同步處理。(結(jié)構(gòu)上的修改是指添加或刪除一個(gè)或多個(gè)映射關(guān)系的任何操作;僅改變與實(shí)例已經(jīng)包含的鍵關(guān)聯(lián)的值不是結(jié)構(gòu)上的修改。)這一般通過(guò)對(duì)自然封裝該映射的對(duì)象進(jìn)行同步操作來(lái)完成。如果不存在這樣的對(duì)象,則應(yīng)該使用?Collections.synchronizedMap?方法來(lái)“包裝”該映射。最好在創(chuàng)建時(shí)完成這一操作,以防止對(duì)映射進(jìn)行意外的非同步訪問(wèn),如下所示:
? ? ??Map m = Collections.synchronizedMap(new HashMap(...));
? ? ??Hashtable 線程安全很好理解,因?yàn)樗總€(gè)方法中都加入了Synchronize。這里我們分析一下HashMap為什么是線程不安全的:
?
? ? ??HashMap底層是一個(gè)Entry數(shù)組,當(dāng)發(fā)生hash沖突的時(shí)候,hashmap是采用鏈表的方式來(lái)解決的,在對(duì)應(yīng)的數(shù)組位置存放鏈表的頭結(jié)點(diǎn)。對(duì)鏈表而言,新加入的節(jié)點(diǎn)會(huì)從頭結(jié)點(diǎn)加入。
我們來(lái)分析一下多線程訪問(wèn):
?
? ? ??(1)在hashmap做put操作的時(shí)候會(huì)調(diào)用下面方法:
?
[java]?view plain?copy
?
?
? ? ??在hashmap做put操作的時(shí)候會(huì)調(diào)用到以上的方法。現(xiàn)在假如A線程和B線程同時(shí)對(duì)同一個(gè)數(shù)組位置調(diào)用addEntry,兩個(gè)線程會(huì)同時(shí)得到現(xiàn)在的頭結(jié)點(diǎn),然后A寫(xiě)入新的頭結(jié)點(diǎn)之后,B也寫(xiě)入新的頭結(jié)點(diǎn),那B的寫(xiě)入操作就會(huì)覆蓋A的寫(xiě)入操作造成A的寫(xiě)入操作丟失
(? ? ??2)刪除鍵值對(duì)的代碼
?
[java]?view plain?copy
?
?
? ? ??當(dāng)多個(gè)線程同時(shí)操作同一個(gè)數(shù)組位置的時(shí)候,也都會(huì)先取得現(xiàn)在狀態(tài)下該位置存儲(chǔ)的頭結(jié)點(diǎn),然后各自去進(jìn)行計(jì)算操作,之后再把結(jié)果寫(xiě)會(huì)到該數(shù)組位置去,其實(shí)寫(xiě)回的時(shí)候可能其他的線程已經(jīng)就把這個(gè)位置給修改過(guò)了,就會(huì)覆蓋其他線程的修改
? ? ??(3)addEntry中當(dāng)加入新的鍵值對(duì)后鍵值對(duì)總數(shù)量超過(guò)門(mén)限值的時(shí)候會(huì)調(diào)用一個(gè)resize操作,代碼如下:
[java]?view plain?copy
?
? ? ??這個(gè)操作會(huì)新生成一個(gè)新的容量的數(shù)組,然后對(duì)原數(shù)組的所有鍵值對(duì)重新進(jìn)行計(jì)算和寫(xiě)入新的數(shù)組,之后指向新生成的數(shù)組。
?
? ? ??當(dāng)多個(gè)線程同時(shí)檢測(cè)到總數(shù)量超過(guò)門(mén)限值的時(shí)候就會(huì)同時(shí)調(diào)用resize操作,各自生成新的數(shù)組并rehash后賦給該map底層的數(shù)組table,結(jié)果最終只有最后一個(gè)線程生成的新數(shù)組被賦給table變量,其他線程的均會(huì)丟失。而且當(dāng)某些線程已經(jīng)完成賦值而其他線程剛開(kāi)始的時(shí)候,就會(huì)用已經(jīng)被賦值的table作為原始數(shù)組,這樣也會(huì)有問(wèn)題。
? ? ??3、是否提供contains方法
?
? ? ??HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey,因?yàn)?/span>contains方法容易讓人引起誤解。
? ? ??Hashtable則保留了contains,containsValue和containsKey三個(gè)方法,其中contains和containsValue功能相同。
我們看一下Hashtable的ContainsKey方法和ContainsValue的源碼:
[java]?view plain?copy
?
?
[java]?view plain?copy
?
?
[java]?view plain?copy
?
? ? ??下面我們看一下HashMap的ContainsKey方法和ContainsValue的源碼:
[java]?view plain?copy
?
?
[java]?view plain?copy
?
?
[java]?view plain?copy
?
通過(guò)上面源碼的比較,我們可以得到第四個(gè)不同的地方
?
? ? ??4、key和value是否允許null值
? ? ??其中key和value都是對(duì)象,并且不能包含重復(fù)key,但可以包含重復(fù)的value。
? ? ??通過(guò)上面的ContainsKey方法和ContainsValue的源碼我們可以很明顯的看出:
? ? ??Hashtable中,key和value都不允許出現(xiàn)null值。但是如果在Hashtable中有類(lèi)似put(null,null)的操作,編譯同樣可以通過(guò),因?yàn)?/span>key和value都是Object類(lèi)型,但運(yùn)行時(shí)會(huì)拋出NullPointerException異常,這是JDK的規(guī)范規(guī)定的。
HashMap中,null可以作為鍵,這樣的鍵只有一個(gè);可以有一個(gè)或多個(gè)鍵所對(duì)應(yīng)的值為null。當(dāng)get()方法返回null值時(shí),可能是 HashMap中沒(méi)有該鍵,也可能使該鍵所對(duì)應(yīng)的值為null。因此,在HashMap中不能由get()方法來(lái)判斷HashMap中是否存在某個(gè)鍵, 而應(yīng)該用containsKey()方法來(lái)判斷。
?
? ? ??5、兩個(gè)遍歷方式的內(nèi)部實(shí)現(xiàn)上不同
? ? ??Hashtable、HashMap都使用了 Iterator。而由于歷史原因,Hashtable還使用了Enumeration的方式 。
6、hash值不同
? ? ??哈希值的使用不同,HashTable直接使用對(duì)象的hashCode。而HashMap重新計(jì)算hash值。
? ? ??hashCode是jdk根據(jù)對(duì)象的地址或者字符串或者數(shù)字算出來(lái)的int類(lèi)型的數(shù)值。
? ? ??Hashtable計(jì)算hash值,直接用key的hashCode(),而HashMap重新計(jì)算了key的hash值,Hashtable在求hash值對(duì)應(yīng)的位置索引時(shí),用取模運(yùn)算,而HashMap在求位置索引時(shí),則用與運(yùn)算,且這里一般先用hash&0x7FFFFFFF后,再對(duì)length取模,&0x7FFFFFFF的目的是為了將負(fù)的hash值轉(zhuǎn)化為正值,因?yàn)?/span>hash值有可能為負(fù)數(shù),而&0x7FFFFFFF后,只有符號(hào)外改變,而后面的位都不變。
7、內(nèi)部實(shí)現(xiàn)使用的數(shù)組初始化和擴(kuò)容方式不同
HashTable在不指定容量的情況下的默認(rèn)容量為11,而HashMap為16,Hashtable不要求底層數(shù)組的容量一定要為2的整數(shù)次冪,而HashMap則要求一定為2的整數(shù)次冪。
? ? ??Hashtable擴(kuò)容時(shí),將容量變?yōu)樵瓉?lái)的2倍加1,而HashMap擴(kuò)容時(shí),將容量變?yōu)樵瓉?lái)的2倍。
? ? ??Hashtable和HashMap它們兩個(gè)內(nèi)部實(shí)現(xiàn)方式的數(shù)組的初始大小和擴(kuò)容的方式。HashTable中hash數(shù)組默認(rèn)大小是11,增加的方式是 old*2+1。
注解詳細(xì):https://blog.csdn.net/wangxing233/article/details/79452946
答:底層數(shù)組+鏈表實(shí)現(xiàn)。
答:初始size為16,擴(kuò)容:newsize = oldsize*2,size一定為2的n次冪
擴(kuò)容針對(duì)整個(gè)Map,每次擴(kuò)容時(shí),原來(lái)數(shù)組中的元素依次重新計(jì)算存放位置,并重新插入。
插入元素后才判斷該不該擴(kuò)容,有可能無(wú)效擴(kuò)容(插入后如果擴(kuò)容,如果沒(méi)有再次插入,就會(huì)產(chǎn)生無(wú)效擴(kuò)容)
當(dāng)Map中元素總數(shù)超過(guò)Entry數(shù)組的75%,觸發(fā)擴(kuò)容操作,為了減少鏈表長(zhǎng)度,元素分配更均勻。
?
答:對(duì)于HashMap而言,key是唯一的,不可以重復(fù)的。?所以,以相同的key 把不同的value插入到 Map中會(huì)導(dǎo)致舊元素被覆蓋,只留下最后插入的元素。?? 不過(guò),同一個(gè)對(duì)象可以作為值插入到map中,只要對(duì)應(yīng)的key不一樣。
ArrayList和Vector使用了數(shù)組的實(shí)現(xiàn),可以認(rèn)為ArrayList或者Vector封裝了對(duì)內(nèi)部數(shù)組的操作,比如向數(shù)組中添加,刪除,插入新的元素或者數(shù)據(jù)的擴(kuò)展和重定向。
LinkedList使用了循環(huán)雙向鏈表數(shù)據(jù)結(jié)構(gòu)。與基于數(shù)組ArrayList相比,這是兩種截然不同的實(shí)現(xiàn)技術(shù),這也決定了它們將適用于完全不同的工作場(chǎng)景。
詳細(xì):https://www.cnblogs.com/wwwcnblogscom/p/8036411.html
7.arrayList和vector的區(qū)別
1. Vector & ArrayList?
1)? Vector的方法都是同步的(Synchronized),是線程安全的(thread-safe),而ArrayList的方法不是,由于線程的同步必然要影響性能,因此,ArrayList的性能比Vector好。?
2) 當(dāng)Vector或ArrayList中的元素超過(guò)它的初始大小時(shí),Vector會(huì)將它的容量翻倍,而ArrayList只增加50%的大小,這樣,ArrayList就有利于節(jié)約內(nèi)存空間。
2. Hashtable & HashMap?
Hashtable和HashMap它們的性能方面的比較類(lèi)似 Vector和ArrayList,比如Hashtable的方法是同步的,而HashMap的不是。
3. ArrayList & LinkedList
ArrayList的內(nèi)部實(shí)現(xiàn)是基于內(nèi)部數(shù)組Object[],所以從概念上講,它更象數(shù)組,但LinkedList的內(nèi)部實(shí)現(xiàn)是基于一組連接的記錄,所以,它更象一個(gè)鏈表結(jié)構(gòu),所以,它們?cè)谛阅苌嫌泻艽蟮牟顒e:?
?????? 從上面的分析可知,在ArrayList的前面或中間插入數(shù)據(jù)時(shí),你必須將其后的所有數(shù)據(jù)相應(yīng)的后移,這樣必然要花費(fèi)較多時(shí)間,所以,當(dāng)你的操作是在一列 數(shù)據(jù)的后面添加數(shù)據(jù)而不是在前面或中間,并且需要隨機(jī)地訪問(wèn)其中的元素時(shí),使用ArrayList會(huì)提供比較好的性能; 而訪問(wèn)鏈表中的某個(gè)元素時(shí),就必須從鏈表的一端開(kāi)始沿著連接方向一個(gè)一個(gè)元素地去查找,直到找到所需的元素為止,所以,當(dāng)你的操作是在一列數(shù)據(jù)的前面或中 間添加或刪除數(shù)據(jù),并且按照順序訪問(wèn)其中的元素時(shí),就應(yīng)該使用LinkedList了。?
?
如果在編程中,1、2兩種情形交替出現(xiàn),這時(shí),你可以考慮使用List這樣的通用接口,而不用關(guān)心具體的實(shí)現(xiàn),在具體的情形下,它的性能由具體的實(shí)現(xiàn)來(lái)保證。
4. 配置集合類(lèi)的初始大小?
??? 在Java集合框架中的大部分類(lèi)的大小是可以隨著元素個(gè)數(shù)的增加而相應(yīng)的增加的,我們似乎不用關(guān)心它的初始大小,但如果我們考慮類(lèi)的性能問(wèn)題時(shí),就一定要考慮盡可能地設(shè)置好集合對(duì)象的初始大小,這將大大提高代碼的性能。?
??? 比如,Hashtable缺省的初始大小為101,載入因子為0.75,即如果其中的元素個(gè)數(shù)超過(guò)75個(gè),它就必須增加大小并重新組織元素,所以,如果你 知道在創(chuàng)建一個(gè)新的Hashtable對(duì)象時(shí)就知道元素的確切數(shù)目如為110,那么,就應(yīng)將其初始大小設(shè)為110/0.75=148,這樣,就可以避免重 新組織內(nèi)存并增加大小。
4.其他面試問(wèn)題(可能會(huì)有上機(jī)題需要手寫(xiě)的)
//不安全的單例模式
//安全的單例模式
public?class?Singleton {
????private?static?volatile?Singleton singleton = null;
??
????private?Singleton(){}
??
????public?static?Singleton getSingleton(){
????????synchronized?(Singleton.class){
????????????if(singleton == null){
????????????????singleton = new?Singleton();
????????????}
????????}
????????return?singleton;
????}???
}
詳細(xì):https://www.cnblogs.com/shan1393/p/8992288.html
?
5.手寫(xiě)冒泡排序 選擇排序? Arrays工具類(lèi)排序:
| package com.bdqn.test; ? import java.util.Arrays; import java.util.Comparator; ? public class SelectSortTest { ?? public static void main(String[] args) { ????? //定義一個(gè)選擇排序的方法 ????? int[] arr= {2,-1,3,4,-9,2,3,5,8}; ????? Integer[] arrInteger= {2,-1,3,4,-9,2,3,5,8}; ????? System.out.println("選擇排序:"); ????? selectSort(arr); ????? System.out.println("冒泡排序:"); ????? puppleSort(arr); ????? System.out.println("使用Arrays工具類(lèi)排排序:"); ????? arraysSort(arrInteger); ?? } ?? private static void selectSort(int[] arr) { ????????? for(int i=0;i<arr.length-1;i++) { ???????????? for(int j=i+1;j<arr.length;j++) { ??????????????? if(arr[i]>arr[j]) { ?????????????????? int temp=arr[i]; ?????????????????? arr[i]=arr[j]; ?????????????????? arr[j]=temp; ??????????????? } ???????????? } ????????? } ????????? //輸出排序后的集合 ????????? System.out.println(Arrays.toString(arr)); ?? } ?? private static void puppleSort(int[] arr) { ????? for(int i=0;i<arr.length-1;i++) { ????????? for(int j=0;j<arr.length-1-i;j++) { ???????????? if(arr[j]>arr[j+1]) { ??????????????? int temp=arr[j]; ??????????????? arr[j]=arr[j+1]; ??????????????? arr[j+1]=temp;? ???????????? } ????????? } ????? } ????? //輸出冒泡排序后的集合 ????? System.out.println(Arrays.toString(arr)); ?? } ?? //使用Arrays類(lèi)實(shí)現(xiàn)排序 ?? public static void arraysSort(Integer[] arr) { ????? Arrays.sort(arr,new Comparator<Integer>() { ????????? @Override ????????? public int compare(Integer o1, Integer o2) { ???????????? return o1-o2; ????????? } ????? }); ????? System.out.println(Arrays.toString(arr)); ?? } }? |
?
答:1.抽象類(lèi)中可以有一個(gè)或多個(gè)抽象方法,而接口中的方法必須都是抽象方法
2.接口中定義方法和成員變量和抽象類(lèi)中定義方法和成員變量接口中成員變量默認(rèn)被修飾為public static final常量
3. 接口最大的一個(gè)特點(diǎn)就是可以實(shí)現(xiàn)多繼承,而抽象類(lèi)智能繼承一個(gè)(應(yīng)該說(shuō)java中只要是類(lèi)就只能單繼承)
4. 4.抽象類(lèi)和方法必須使用abstract關(guān)鍵聲明為抽象,而接口中的方法默認(rèn)被修飾為public abstract類(lèi)型(默認(rèn)為公開(kāi)抽象的方法)
詳細(xì):https://baijiahao.baidu.com/s?id=1568702144789321&wfr=spider&for=pc
答:1.封裝、繼承、多態(tài)
理解:
封裝:把一類(lèi)對(duì)象,相似的屬性匯總到一起,組成一類(lèi),這個(gè)類(lèi)把該隱藏的隱藏,該暴露的暴露。
繼承:涉及到父子類(lèi)的關(guān)系,自然可以得到父類(lèi)的特征,相對(duì)是父類(lèi)的擴(kuò)展,達(dá)到代碼重用的效果。
例如:Java中用extends關(guān)鍵字,實(shí)現(xiàn)繼承類(lèi)被稱(chēng)為子類(lèi),被繼承類(lèi)被稱(chēng)為父類(lèi)。例如:水果和蘋(píng)果的關(guān)系,蘋(píng)果繼承了水果,蘋(píng)果是水果的子類(lèi),水果是蘋(píng)果的父類(lèi)。
詳細(xì):https://blog.csdn.net/kisscatforever/article/details/79721937
String最慢的原因:
String為字符串常量,而StringBuilder和StringBuffer均為字符串變量,即String對(duì)象一旦創(chuàng)建之后該對(duì)象是不可更改的,但后兩者的對(duì)象是變量,是可以更改的。
2. 再來(lái)說(shuō)線程安全
在線程安全上,StringBuilder是線程不安全的,而StringBuffer是線程安全的
如果一個(gè)StringBuffer對(duì)象在字符串緩沖區(qū)被多個(gè)線程使用時(shí),StringBuffer中很多方法可以帶有synchronized關(guān)鍵字,所以可以保證線程是安全的,但StringBuilder的方法則沒(méi)有該關(guān)鍵字,所以不能保證線程安全,有可能會(huì)出現(xiàn)一些錯(cuò)誤的操作。所以如果要進(jìn)行的操作是多線程的,那么就要使用StringBuffer,但是在單線程的情況下,還是建議使用速度比較快的StringBuilder。
?總結(jié)一下
String:適用于少量的字符串操作的情況
StringBuilder:適用于單線程下在字符緩沖區(qū)進(jìn)行大量操作的情況
StringBuffer:適用多線程下在字符緩沖區(qū)進(jìn)行大量操作的情況
?? 詳細(xì):https://www.cnblogs.com/su-feng/p/6659064.html
例:insert into Strdents (姓名,性別,出生日期) values ('開(kāi)心朋朋','男','1980/6/15')
?delete from a where name='開(kāi)心朋朋'(刪除表a中列值為開(kāi)心朋朋的行)
例:update tongxunlu set 年齡=18 where 姓名='藍(lán)色小名'
詳細(xì):https://www.cnblogs.com/daxueshan/p/6687521.html
1.去重 DISTINCT?
不同項(xiàng)目之間的通信方式分為,http、socket、webservice;其中socket通信的效率最高,youtube就采用的是原始的socket通信,他們信奉的原則是簡(jiǎn)單有效。
一、http通信:
????Http通信主要有兩種方式POST方式和GET方式。前者通過(guò)Http消息實(shí)體發(fā)送數(shù)據(jù)給服務(wù)器,安全性高,數(shù)據(jù)傳輸大小沒(méi)有限制,后者通過(guò)URL的查詢字符串傳遞給服務(wù)器參數(shù),以明文顯示在瀏覽器地址欄,保密性差,最多傳輸2048個(gè)字符。但是GET請(qǐng)求并不是一無(wú)是處——GET請(qǐng)求大多用于查詢(讀取資源),效率高。POST請(qǐng)求用于注冊(cè)、登錄等安全性較高且向數(shù)據(jù)庫(kù)中寫(xiě)入數(shù)據(jù)的操作。除了POST和GET,http通信還有其他方式!請(qǐng)參見(jiàn)http請(qǐng)求的方法
二、webservice
應(yīng)用場(chǎng)景:跨防火墻的通信、應(yīng)用程序集成、B2B的集成、軟件和數(shù)據(jù)重用
三、socket
socket是“open—write/read—close”模式的一種實(shí)現(xiàn)
java socket通信已經(jīng)被封裝好了主要使用兩個(gè)類(lèi)ServerSocket 和Socket
詳細(xì):https://blog.csdn.net/sunshine_silence/article/details/78771198
?
框架面試問(wèn)題(簡(jiǎn)歷上有寫(xiě)的就會(huì)問(wèn)到,沒(méi)寫(xiě)的他們公司要求用到的也可能會(huì)問(wèn))
5.Spring面試問(wèn)題
Spring的三大核心思想:IOC(控制反轉(zhuǎn)),DI(依賴(lài)注入),AOP(面向切面編程)。
?
(1)IOC(控制反轉(zhuǎn))
實(shí)現(xiàn)將組件間的關(guān)系從程序內(nèi)部提到外部容器(spring的xml)來(lái)管理首先外部容器(spring.xml)中會(huì)動(dòng)態(tài)的注冊(cè)業(yè)務(wù)所需的對(duì)象(接口/類(lèi))
(2)DI(依賴(lài)注入)
組件之間的依賴(lài)關(guān)系由容器在應(yīng)用系統(tǒng)運(yùn)行期來(lái)決定, 也就是由容器動(dòng)態(tài)地將某種依賴(lài)關(guān)系的目標(biāo)對(duì)象實(shí)例注入到應(yīng)用系統(tǒng)中的各個(gè)關(guān)聯(lián)的組件之中
(3)?AOP(面向切面編程)?
??利用一種稱(chēng)為"橫切"的技術(shù),剖解開(kāi)封裝的對(duì)象內(nèi)部,并將那些影響了多個(gè)類(lèi)的公共行為封裝到一個(gè)可重用模塊,并將其命名為"Aspect",即切面。所謂"切面",簡(jiǎn)單說(shuō)就是那些與業(yè)務(wù)無(wú)關(guān),卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯或責(zé)任封裝起來(lái),便于減少系統(tǒng)的重復(fù)代碼,降低模塊之間的耦合度,并有利于未來(lái)的可操作性和可維護(hù)性。
詳細(xì)https://blog.csdn.net/u010688011/article/details/79431778
就是讓對(duì)象與對(duì)象(模塊與模塊)之間的關(guān)系沒(méi)有通過(guò)代碼來(lái)關(guān)聯(lián),都是通過(guò)配置類(lèi)說(shuō)明管理的(Spring根據(jù)這些配置 內(nèi)部通過(guò)反射去動(dòng)態(tài)的組裝對(duì)象)?
?
詳細(xì):https://www.cnblogs.com/zhoudi/p/5820513.html?
??1: 想辦法讓action具有 自動(dòng)注入的功能;
??2: 讓action納入spring管理;
? ?????spring與hibernate整合兩種方式:
1. 零障礙整合;
2. Spring管理hibernate配置;
?1.零障礙整合:
?在spring的配置文件applicationContext.xml中配置bean: 并引入hibernate的核心配置文件;
2.spring管理hibernate配置:將hibernate的核心配置文件 hibernate.cfg.xml中的內(nèi)容遷移到 applicationContext.xml中;
SSM:
1、dao層
1.1、必須數(shù)據(jù):
pojo(java實(shí)體)、mapper接口(dao接口)、sql映射文件(翻譯為jdbc中的statement)
1.2、配置文件:
mybatis核心配置文件:SqlMapConfig.xml
自定義別名
spring整合mybatis配置文件:applicationContext-dao.xml
數(shù)據(jù)源
會(huì)化工廠
mapper掃描(加載dao)
其他配置:
數(shù)據(jù)庫(kù)信息:db.properties
日志信息:log4j.properties
2、service層
2.1、配置文件:
注解掃描:@service(加載service)applicationContext-service.xml
事務(wù)配置: ApplicationContext-trans.xml
3、controller層
3.1、配置文件: springMVC.xml
注解掃描:@controller(加載controller)
注解驅(qū)動(dòng):自動(dòng)加載最新的處理器映射器、處理器適配器
視圖解析器:
自定義類(lèi)型轉(zhuǎn)化器:(掛載于注解驅(qū)動(dòng))
文件上傳解析器:
json格式數(shù)據(jù)解析器:(若沒(méi)有配置注解驅(qū)動(dòng),則需要顯示的在處理器適配器掛載)
全局異常處理器:
自定義攔截器:
靜態(tài)資源放行:
4、web.xml web.xml
4.1、spring監(jiān)聽(tīng)器
4.2、springMVC前端控制器
4.3、post中文亂碼請(qǐng)求
原文:https://blog.csdn.net/u010758410/article/details/80145521
4.1先以靜態(tài)代理實(shí)現(xiàn),靜態(tài)代理關(guān)鍵是在代理對(duì)象和目標(biāo)對(duì)象實(shí)現(xiàn)共同的接口,并且代理對(duì)象持有目標(biāo)對(duì)象的引用。
4.2:動(dòng)態(tài)代理實(shí)現(xiàn)主要是實(shí)現(xiàn)InvocationHandler,并且將目標(biāo)對(duì)象注入到代理對(duì)象中,利用反射機(jī)制來(lái)執(zhí)行目標(biāo)對(duì)象的方法。
6.SpingMVC面試問(wèn)題
?一、框架機(jī)制
spring mvc 和 struts2的加載機(jī)制不同:spring mvc的入口是servlet,而struts2是filter(servlet和filter區(qū)別見(jiàn)本文最后)
1、Struts2采用Filter(StrutsPrepareAndExecuteFilter)實(shí)現(xiàn),SpringMVC(DispatcherServlet)則采用Servlet實(shí)現(xiàn)。
2、Filter在容器啟動(dòng)之后即初始化;服務(wù)停止以后墜毀,晚于Servlet。Servlet在是在調(diào)用時(shí)初始化,先于Filter調(diào)用,服務(wù)停止后銷(xiāo)毀。
二、攔截機(jī)制
1、Struts2
a、Struts2框架是類(lèi)級(jí)別的攔截,每次請(qǐng)求就會(huì)創(chuàng)建一個(gè)Action,和Spring整合時(shí)Struts2的ActionBean注入作用域是原型模式prototype(否則會(huì)出現(xiàn)線程并發(fā)問(wèn)題),然后通過(guò)setter,getter吧request數(shù)據(jù)注入到屬性。
b、Struts2中,一個(gè)Action對(duì)應(yīng)一個(gè)request,response上下文,在接收參數(shù)時(shí),可以通過(guò)屬性接收,這說(shuō)明屬性參數(shù)是讓多個(gè)方法共享的。
c、Struts2中Action的一個(gè)方法可以對(duì)應(yīng)一個(gè)url,而其類(lèi)屬性卻被所有方法共享,這也就無(wú)法用注解或其他方式標(biāo)識(shí)其所屬方法了
?
2、SpringMVC
a、SpringMVC是方法級(jí)別的攔截,一個(gè)方法對(duì)應(yīng)一個(gè)Request上下文,所以方法直接基本上是獨(dú)立的,獨(dú)享request,response數(shù)據(jù)。而每個(gè)方法同時(shí)又何一個(gè)url對(duì)應(yīng),參數(shù)的傳遞是直接注入到方法中的,是方法所獨(dú)有的。處理結(jié)果通過(guò)ModeMap返回給框架。
b、在Spring整合時(shí),SpringMVC的Controller Bean默認(rèn)單例模式Singleton,所以默認(rèn)對(duì)所有的請(qǐng)求,只會(huì)創(chuàng)建一個(gè)Controller,有應(yīng)為沒(méi)有共享的屬性,所以是線程安全的,如果要改變默認(rèn)的作用域,需要添加@Scope注解修改。
三、性能方面
SpringMVC實(shí)現(xiàn)了零配置,由于SpringMVC基于方法的攔截,有加載一次單例模式bean注入。而Struts2是類(lèi)級(jí)別的攔截,每次請(qǐng)求對(duì)應(yīng)實(shí)例一個(gè)新的Action,需要加載所有的屬性值注入,所以,SpringMVC開(kāi)發(fā)效率和性能高于Struts2。
四、攔截機(jī)制
Struts2有自己的攔截Interceptor機(jī)制,SpringMVC這是用的是獨(dú)立的Aop方式,這樣導(dǎo)致Struts2的配置文件量還是比SpringMVC大。
五、配置方面
spring MVC和Spring是無(wú)縫的。從這個(gè)項(xiàng)目的管理和安全上也比Struts2高(當(dāng)然Struts2也可以通過(guò)不同的目錄結(jié)構(gòu)和相關(guān)配置做到SpringMVC一樣的效果,但是需要xml配置的地方不少)。
SpringMVC可以認(rèn)為已經(jīng)100%零配置。
六、設(shè)計(jì)思想
Struts2更加符合OOP的編程思想, SpringMVC就比較謹(jǐn)慎,在servlet上擴(kuò)展。
七、集成方面
SpringMVC集成了Ajax,使用非常方便,只需一個(gè)注解@ResponseBody就可以實(shí)現(xiàn),然后直接返回響應(yīng)文本即可,而Struts2攔截器集成了Ajax,在Action中處理時(shí)一般必須安裝插件或者自己寫(xiě)代碼集成進(jìn)去,使用起來(lái)也相對(duì)不方便。
1.適配器? 試圖解析器? 映射器
MVC是Model—View—Controler的簡(jiǎn)稱(chēng)。即模型—視圖—控制器。MVC是一種設(shè)計(jì)模式,它強(qiáng)制性的把應(yīng)用程序的輸入、處理和輸出分開(kāi)。
MVC中的模型、視圖、控制器它們分別擔(dān)負(fù)著不同的任務(wù)。
視圖: 視圖是用戶看到并與之交互的界面。視圖向用戶顯示相關(guān)的數(shù)據(jù),并接受用戶的輸入。視圖不進(jìn)行任何業(yè)務(wù)邏輯處理。
模型: 模型表示業(yè)務(wù)數(shù)據(jù)和業(yè)務(wù)處理。相當(dāng)于JavaBean。一個(gè)模型能為多個(gè)視圖提供數(shù)據(jù)。這提高了應(yīng)用程序的重用性
控制器: 當(dāng)用戶單擊Web頁(yè)面中的提交按鈕時(shí),控制器接受請(qǐng)求并調(diào)用相應(yīng)的模型去處理請(qǐng)求。
然后根據(jù)處理的結(jié)果調(diào)用相應(yīng)的視圖來(lái)顯示處理的結(jié)果。
MVC的處理過(guò)程:首先控制器接受用戶的請(qǐng)求,調(diào)用相應(yīng)的模型來(lái)進(jìn)行業(yè)務(wù)處理,并返回?cái)?shù)據(jù)給控制器。控制器調(diào)用相應(yīng)的視圖來(lái)顯示處理的結(jié)果。并通過(guò)視圖呈現(xiàn)給用戶。
詳細(xì):https://www.cnblogs.com/Alexander11/p/5621560.html
7.Struts2面試題
1普通的POJO類(lèi),該類(lèi)通常包含一個(gè)無(wú)參數(shù)的execute()方法,返回值為字符串類(lèi)型。
2實(shí)現(xiàn)Action接口
3繼承ActionSupport類(lèi)
? 首先運(yùn)行項(xiàng)目 所有請(qǐng)求被攔截器 攔截 然后交給Action 把數(shù)據(jù)返回給jsp頁(yè)面
8.MyBatis和Hibernate
答:1:hibernate是全自動(dòng),而mybatis是半自動(dòng)。
2.Hibernate數(shù)據(jù)庫(kù)移植性遠(yuǎn)大于mybatis
3.hibernate擁有完整的日志系統(tǒng),mybatis則欠缺些
4.mybatis相比hibernate需要關(guān)系很多細(xì)節(jié)
5.sql直接優(yōu)化上,mybatis要比hibernate方便很多
? ??總結(jié):
Mybatis:小巧、方便、高效、簡(jiǎn)單、直接、半自動(dòng)
Hibernate:強(qiáng)大、方便、高效、復(fù)雜、繞彎子、全自動(dòng)
詳細(xì):https://blog.csdn.net/w_q_q_/article/details/79032062
9.Dubbo面試問(wèn)題
Dobbo是一個(gè)分布式框架,致力提供高性能和透明化的 PRC遠(yuǎn)程服務(wù)調(diào)用方案。簡(jiǎn)單說(shuō):,dobbo就是個(gè)服務(wù)框架,如果沒(méi)有分布式需求,其實(shí)不需要要用的,只要在分布式的時(shí)候,才有dubbo這樣的分布式服務(wù)框架的需求,并且本質(zhì)是個(gè)服務(wù)調(diào)用的東東,說(shuō)白了就是個(gè)遠(yuǎn)程調(diào)用分布式框架。
其核心部分包含:
1. 遠(yuǎn)程通訊: 提供對(duì)多種基于長(zhǎng)連接的NIO框架抽象封裝,包括多種線程模型,序列化,以及“請(qǐng)求-響應(yīng)”模式的信息交換方式。
2. 集群容錯(cuò): 提供基于接口方法的透明遠(yuǎn)程過(guò)程調(diào)用,包括多協(xié)議支持,以及軟負(fù)載均衡,失敗容錯(cuò),地址路由,動(dòng)態(tài)配置等集群支持。
3. 自動(dòng)發(fā)現(xiàn): 基于注冊(cè)中心目錄服務(wù),使服務(wù)消費(fèi)方能動(dòng)態(tài)的查找服務(wù)提供方,使地址透明,使服務(wù)提供方可以平滑增加或減少機(jī)器。
詳細(xì):https://blog.csdn.net/houshaolin/article/details/76408399
默認(rèn)調(diào)用netty框架,還有mian以及基于servlet等方式。
詳細(xì):https://www.cnblogs.com/yang-lq/p/9168216.html
默認(rèn)是阻塞的,可以異步調(diào)用,沒(méi)有返回值的可以這么做。
推薦使用zookeeper注冊(cè)中心,還有Multicast、Redis和Simple等。
2. zookeeper中有兩種類(lèi)型的節(jié)點(diǎn):
1.持久節(jié)點(diǎn)(PERSISENT):一旦創(chuàng)建,除非主動(dòng)調(diào)用刪除操作,否則一直存儲(chǔ)在zk上;
2.臨時(shí)節(jié)點(diǎn)(EPHEMERAL):與客戶端會(huì)話綁定,一旦客戶端會(huì)話失效,這個(gè)客戶端所創(chuàng)建的所有臨時(shí)節(jié)點(diǎn)都會(huì)被移除;
??詳細(xì):https://www.jianshu.com/p/f42c69e4bd3e?fromApp=1
可以直連,修改配置即可,也可以通過(guò)telnet直接某個(gè)服務(wù)。
10.SpringBoot面試問(wèn)題
SpringBoot+maven? 簡(jiǎn)化搭建以及開(kāi)發(fā)過(guò)程 是一個(gè)非常好的微服務(wù)開(kāi)發(fā)框架 可以快速搭建一個(gè)系統(tǒng)
配置少 開(kāi)發(fā)和部署效率快?
詳細(xì):https://blog.csdn.net/m0_38075425/article/details/81164501
?
總結(jié)
以上是生活随笔為你收集整理的2019java 开发工程师 最新面试官 问的问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 科技“度”善
- 下一篇: 和菜头:在碎片化的轰炸中喘息