面試之Java知識整理。本站提示廣大學習愛好者:(面試之Java知識整理)文章只能為提供參考,不一定能成為您想要的結果。以下是面試之Java知識整理正文
1.面向對象都有哪些特性
承繼、封裝、多態性、籠統
2.Java中完成多態的機制是什麼?
承繼與接口
3.Java中異常分為哪些品種
3.1依照異常需求處置的機遇分為編譯時異常(CheckedException)和運轉時異常(RuntimeException)。
3.2關於編譯時異常的處置辦法有兩種:
(1)以後辦法知道如何處置該異常,則用try…catch塊來處置該異常。
(2)以後辦法不知道如何處置,則在定義該辦法時聲明拋出該異常。
3.3運轉時異常,假如顯式聲明或許捕捉將會對順序的可讀性和運轉效率影響很大,所以由零碎自動檢測並將它們交給缺省的異常處置順序,當然假如有處置要求也可以顯式捕捉它們。
4.Java的數據類型
4.1Java的根本數據類型都有哪些,各占幾個字節
Byte 1 char 2 short 2 int 4 float 4 double 8 long 8 boolean 1
4.2ing是根本數據類型嗎?可以被承繼嗎?
String是援用類型,底層用char數組完成的。由於String是final類,在java中被final修飾的類不能被承繼,因而String當然不可以被承繼。
5.Java的IO
5.1.Java中有幾品種型的流
字節流和字符流。字節流承繼於InputStream和OutputStream,字符流承繼於InputStreamReader和OutputStreamWriter。
5.2字節流如何轉為字符流
字節輸出流轉字符輸出流經過InputStreamReader完成,該類的結構函數可以傳入InputStream對象。
字節輸入流轉字符輸入流經過OutputSreamWriter完成,該類的結構函數可以傳入OutputStream對象。
6.Java的集合
6.1ArrayList、HashSet、HashMap是線程平安的嗎?假如不是想要的線程平安的集合怎樣辦?
每個辦法都沒有加鎖,顯然都是線程不平安的。
在集合中Vector和HashTable是線程平安的。
Collections工具類提供了相關的API,可以讓下面3個不平安的集合變為平安,如下:
Collections.synchronizedCollection(c)
Collections.synchronizedList(list)
Collections.synchronizedMap(m)
Collections.synchronizedSet(s)
6.2並發集合和普通集合如何區別?
並發集合罕見的有ConCurrentHashMap、ConcurrentLinkedQueue、ConcurrentLinkedDeque等。並發集合位於java.util.concurrent包下,是jdk1.5之後才有的,次要作者是Doug Lea(http://baike.baidu.com/view/3141057.http)完成的。
在java中有普通集合、同步(線程平安)的集合、並發集合。普通集合通常功能最高,但是不保證多線程的平安性和並發的牢靠性。線程平安集合僅僅是給集合添加了synchronized同步鎖,嚴重犧牲了功能,而且對並發的效率就更低了,並發集合則經過復雜的戰略不只保證了多線程的平安又進步的並發時的效率。
ConcurrentHashMap是線程平安的HashMap的完成,默許結構異樣有initialCapacity和loadFactor屬性,不過還多了一個concurrencyLevel屬性,三屬性默許值辨別為16、0.75及16。其外部運用鎖分段技術,維持著鎖Segment的數組,在Segment數組中又寄存著Entity[]數組,外部hash算法將數據較平均散布在不同鎖中。
Put操作:並沒有在此辦法上加上synchronized,首先對key.hashcode停止hash操作,失掉key的hash值。Hash操作的算法和map不同,依據此hash值計算並獲取其對應的數組中的Segment對象(承繼自ReentrantLock),接著調用此Segment對象的put辦法來完成以後操作。
ConcurrentHashMap基於concurrencyLevel劃分出了多個Segment來對key-value停止存儲,從而防止每次put操作都得鎖住整個數組。在默許的狀況下,最佳狀況下可允許16個線程並發無阻塞的操作集合對象,盡能夠地增加並發時的阻塞景象。
Get(key)
首先對key.hashCode停止hash操作,基於其值找到對應的Segment對象,調用其get辦法完成以後操作。而Segment的get操作首先經過hash值和對象數組大小減1的值停止按位與操作來獲取數組上對應地位的HashEntry。在這個步驟中,能夠會由於對象數組大小的改動,以及數組上對應地位的HashEntry發生不分歧性,那麼ConcurrentHashMap是如何保證的?
對象數組大小的改動只要在put操作時有能夠發作,由於HashEntry對象數組對應的變量是volatile類型的,因而可以保證如HashEntry對象數組大小發作改動,讀操作可看到最新的對象數組大小。
在獲取到了HashEntry對象後,怎樣能保證它及其next屬性構成的鏈表上的對象不會改動呢?這點ConcurrentHashMap采用了一個復雜的方式,即HashEntry對象中的hash、key、next屬性都是final的,這也就意味著沒方法拔出一個HashEntry對象到基於next屬性構成的鏈表兩頭或末尾。這樣就可以保證當獲取到HashEntry對象後,其基於next屬性構建的鏈表是不會發作變化的。
ConcurrentHashMap默許狀況下采用將數據分為16個段停止存儲,並且16個段辨別持有各自不同的鎖Segment,鎖僅用於put和remove等改動集合對象的操作,基於volatile及HashEntry鏈表的不變性完成了讀取的不加鎖。這些方式使得ConcurrentHashMap可以堅持極好的並發支持,尤其是關於讀取比拔出和刪除頻繁的Map而言,而它采用的這些辦法也可謂是關於Java內存模型、並發機制深入掌握的表現。
7.Java的多線程
7.1多線程的兩種創立方式
Java.lang.Thread類的實例就是一個線程但是它需求調用java.lang.Runnable接口來執行,由於線程類自身就是調用的Runnable接口所以可以承繼java.lang.Thread類或許直接完成Runnable接口來重寫run()辦法完成線程。
7.2在java中wait和sleep辦法的不同?
最大的不同是在等候時wait會釋放鎖,而sleep不斷持有鎖。Wait通常被用於線程間交互,sleep通常被用於暫停執行。
7.3synchronized和volatile關鍵字的作用
一旦一個共享變量(類的成員變量、類的靜態成員變量)被volatile修飾之後,那麼就具有了兩層語義:
(1)保證了不同線程對這個變量停止操作時的可見性,即一個線程修正了某個變量的值,這新值對其他線程來說是立刻可見的。
(2)制止停止指令重排序。
Volatile實質是在通知jvm以後變量在存放器(任務內存)中的值是不確定的,需求從主存中讀取;
Synchronized則是鎖定以後變量,只要以後線程可以訪問該變量,其他線程被阻塞住。
(1)volatile僅能運用在變量級別;synchronized則可以運用在變量、辦法和類級別的。
(2)volatile僅能完成變量的修正可見性,並不能保證原子性;synchronized則可以保證變量的修正可見性和原子性。
(3)volatile不會形成線程的阻塞;synchronized能夠會形成線程的阻塞。
(4)volatile標志的變量不會被編譯器優化;synchronized標志的變量可以被編譯器優化。
7.4什麼是線程池,如何運用
線程池就是事前將多個線程對象放到一個容器中,當運用的時分就不必new線程而是直接去池中拿線程即可,節省了開拓子線程的時間,進步了代碼的執行效率。
在JDK的java.util.concurrent.Executors中提供了生成多種線程池的靜態辦法:
ExecutorService newCanchedThreadPool = Excutors.newCachedThreadPool();
ExecutorService newFixedThreadPool = Excutors.newFixedThreadPool(4);
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(4);
ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
然後調用他們的execute辦法即可。
7.5線程池的了解
說一下線程池如何用、線程池的益處、線程池的啟動戰略
合理應用線程池可以帶來三個益處:
第一:降低資源耗費。經過反復應用已創立的線程降低線程創立和銷毀形成的耗費。
第二:進步呼應速度。當義務抵達時,義務可以不需求等到線程創立就能立刻執行。
第三:進步線程的可管感性。線程是稀缺資源,假如有限制的創立,不只會耗費零碎資源,還會降低零碎的波動性,運用線程池可以停止一致的分配、調優和監控。
7.6線程池的啟動戰略
(1)線程池剛創立時,外面沒有一個線程。義務隊列是作為參數傳出去的。不過,就算隊列外面有義務,線程池也不會馬上執行它們。
(2)當調用execute()辦法添加一個義務時,線程池會做如下判別:
a.假如正在執行的線程數量小於corePoolSize,那麼馬上創立線程運轉這個義務;
b.假如正在執行的線程數量大於或等於corePoolSize,那麼將這個義務放入隊列;
c.假如這時分隊列滿了,而且正在執行的線程數量小於maximumPoolSize,那麼還是要創立線程運轉這個義務;
d.假如隊列滿了,而且正在運轉的線程數量大於或等於maximumPoolSize,那麼線程池會拋出異常,通知調用者“不能再承受義務了”。
(3)當一個線程完成義務時,它會從隊列中取下一個義務來執行。
(4)當一個線程無事可做,超越一定的時間(keyAliveTime)時,線程池會判別,假如以後運轉的線程數大於corePoolSize,那麼這個線程就被停掉。所以線程池的一切義務完成後,它最終會膨脹到coorPoolSize的大小。
7.7如何控制某個辦法允許並發訪問線程的大小?
可以運用Semaphore控制,就是信號,初始化n個信號,在線程中,運轉semaphore.acquire()請求懇求,這樣最多只能有n個線程並發訪問,多余n個線程時就排隊等候。線程完成後釋放信號,這樣新的線程就可以運用了。
8.Java中的反射
8.1Java中反射的了解
Java中的反射首先是可以獲取到Java中要反射類的字節碼,獲取字節碼有三種辦法,1.Class.forName(className)2.類名.Class3.this.getClass()。然後將字節碼中的辦法、變量、結構函數等映射成相應的Method、Filed、Contructor等類,這些類提供了豐厚的辦法可以被運用。
8.2動態態代理的區別,什麼場景運用?
靜態代理通常只代理一個類,靜態代理是代理一個接口下的多個完成類。
靜態代理事前知道要代理的是什麼,而靜態代理不知道要代理什麼東西,只要在運轉時才知道。
靜態代理是顯示JDK裡的InvocationHandler接口的invoke辦法,但留意的是代理的是接口,也就是業務類必需要完成接口,經過Proxy裡的newProxyInstance失掉代理對象。
還有一種靜態代理CGLIB,代理的是類,不需求業務類承繼接口,經過派生的子類來完成代理。經過在運轉時,靜態修正字節碼到達修正類的目的。
AOP編程就是基於靜態代理完成的,比方著名的Spring框架、Hibernate框架等等都是靜態代理的運用例子。
9.Java中的回收機制
9.1.Java渣滓回收機制和罕見算法
Sun公司只定義了渣滓回收機制規則而不局限於其完成算法,因而不同廠商消費的虛擬機采用的算法也不盡相反。
GC(Garbage Collector)在回收對象前首先必需發現那些無用的對象,如何去發現定位這些無用的對象?通常的搜素算法如下:
(1)援用計數器算法(廢棄)
援用計數器算法是給每個對象設置一個計數器,當有中央援用這個對象的時分,計數器+1,當援用生效的時分,計算器-1,當計數器為0的時分,JVM就以為對象不再被運用,是“渣滓”了。
援用計數器完成復雜,效率高;但是不能處理循環援用問題(A對象援用B對象,B對象援用A對象,但是A,B對象已不再被任何其他對象援用),同時每次計數器的添加和增加都帶來了很多額定的開支,所以在JDK1.1之後,這個算法就不再運用了。
(2)根搜索算法(運用)
根搜素算法是經過一些“GC Roots”對象作為終點,從這些節點開端往下搜索,搜索經過的途徑成為援用鏈(Reference Chain),當一個對象沒有被GC Roots的援用鏈銜接的時分,闡明這個對象是不可用的。
GC Roots對象包括:
a.虛擬機棧(棧幀中的本地變量表)中的援用的對象。
b.辦法區域中的類靜態屬性援用的對象。
c.辦法區域中常量援用的對象。
d.本中央法棧中JNI(Native辦法)的援用的對象。
經過下面的算法搜索到無用對象之後,就是回收進程,回收算法如下:
(1)標志-肅清算法(Mark-Sweep)(DVM運用的算法)
標志-肅清算法包括連個階段:“標志”和“肅清”。在標志階段,確定一切要回收的對象,並做標志。肅清階段緊隨標志階段,將標志階段確定不可用的對象肅清。標志-肅清算法是根底的搜集算法,標志和肅清階段的效率不高,而且清楚後回發生少量的不延續空間,這樣當順序需求分配大內存對象時,能夠無法找到足夠的延續空間。
(2)復制算法(Copying)
復制算法是把內存分紅大小相等的兩塊,每次運用其中一塊,當渣滓回收的時分,把存活的對象復制到另一塊上,然後把這塊內存整個清算掉。復制算法完成復雜,運轉效率高,但是由於每次只能運用其中的一半,形成內存的應用率不高。如今的JVM用復制辦法搜集重生代,由於重生代中大局部對象(98%)都是朝生夕死的,所以兩塊內存的比例不是1:1(大約是8:1)。
(3)標志-整理算法(Mark-Compact)
標志-整理算法和標志-肅清算法一樣,但是標志-整理算法不是把存活對象復制到另一塊內存,而是把存活對象往內存的一端挪動,然後直接回收邊界以外的內存。標志-整理算法進步了內存的應用率,並且它合適在搜集對象存活時間較長的老年代。
(4)分代搜集(Generational Collection)
分代搜集是依據對象的存活時間把內存分為重生代和老生代,依據各個代對象的存活特點,每個代采用不同的渣滓回收算法。重生代采用復制算法,老生代采用標志-整理算法。渣滓算法的完成觸及少量的順序細節,而且不同的虛擬機平台完成的辦法也各不相反。
9.2.JVM的內存構造和內存分配
(1)java內存模型
Java虛擬機將其管轄的內存大致分三個邏輯局部:辦法區(Method Area)、Java棧和Java堆。
a.辦法區是靜態分配的,編譯器將變量綁定在某個存儲地位上,而且這些綁定不會再運轉時改動。常數池,源代碼中的命名常量、String常量和static變量保管在辦法區。
b.Java Stack是一個邏輯概念,特點是後進先出。一個棧的空間能夠是延續的,也能夠是不延續的。最典型的Stack使用是辦法的調用,Java虛擬機每調用一次辦法就創立一個辦法幀(frame),加入該辦法則對應的辦法幀被彈出(pop)。棧中存儲的數據也是運轉時確定的。
c.Java堆分配(heap allocation)意味著以隨意的順序,在運轉時停止存儲空間分配和回收的內存管理模型。堆中存儲的數據經常是大小、數量和生命期在編譯時無法確定的。Java對象的內存總是在heap中分配。
(2)Java內存分配
a.根底數據類型直接在棧空間分配。
b.辦法的方式參數,直接在棧空間分配,當辦法調用完成後從棧空間回收。
c.援用數據類型,需求用new來創立,即在棧空間分配一個地址空間,又在堆空間分配對象的類變量。
d.辦法的援用參數,在棧空間分配一個地址空間,並指向堆空間的對象區,當辦法調用完後從棧空間回收。
e.部分變量new出來時,在棧空間和堆空間中分配空間,當部分變量生命周期完畢後,棧空間立刻被回收,堆空間區域等候GC回收。
f.辦法調用時傳入的實踐參數,如今棧空間分配,在辦法調用完成後從棧空間釋放。
g.字符串常量在DATA區域分配,this在堆空間分配。
h.數組即在棧空間分配數組稱號,又在堆空間分配數組實踐的大小。
9.3.Java中援用類型都有哪些?
Java中對象的援用分為四種級別,這四種級別由高到低順次為:強援用、軟援用、弱援用和虛援用。
(1)強援用
假如一個對象被人擁有強援用,那麼渣滓回收器絕不會回收它。當內存空間缺乏,Java虛擬機寧願拋出OutOfMemoryError錯誤,使順序異常終止,也不會靠隨意回收具有強援用的對象阿裡處理內存缺乏問題。
Java的對象是位於heap中的,heap中對象有強可及對象、軟可及對象、弱可及對象、虛可及對象和不可抵達對象。使用的強弱順序是強、軟、弱和虛。關於對象是屬於哪種可及的對象,由他的最強的援用決議。
String abc = new String(“abc”);//強援用,abc為強可及
SoftReference<String> softRef = new SoftReference<String>(abc);//軟援用
WeakReference<String> weakRef = new WeakReference<String>(abc);//弱援用
abc=null;//abc軟可及
softRef.clear();//abc變成弱可及
(2)軟援用
假如一個對象只具有軟援用,那麼假如內存空間足夠,渣滓回收器就不會回收它,假如內存空間缺乏了,就會回收這些對象的內存。只需渣滓回收器沒有回收它,該對象就可以被順序運用。軟援用可用來完成內存敏感的高速緩存。
軟援用可以和一個援用隊列(ReferenceQueue)結合運用,假如軟援用所援用的對象被渣滓回收器回收,Java虛擬機就會把這個軟援用參加到與之關聯的援用隊列中。
軟援用次要用於內存敏感的高速緩存。在jvm報告內存缺乏之前會肅清一切的軟援用,這樣以來gc就有能夠手機軟可及的對象,能夠處理內存吃緊問題,防止內存溢出。什麼時分會被搜集取決於gc的算法和gc運轉時可用內存的大小。當gc決議要搜集軟援用時執行步驟如下:(以下面的softRef為例)
a.首先將softRef的referent(abc)設置為null,不再援用heap中的new String(“abc”)對象。
b.將heap中的new String(“abc”)對象設置為可完畢的(finalizable)。
c.當heap中的new String(“abc”)對象的finalize()辦法被運轉而且該對象占用的內存被釋放,softRef被添加到它的ReferenceQueue(假如有的話)中。
留意:對ReferenceQueue軟援用和弱援用可有可無,但虛援用必需有。
被Soft Reference指到的對象,即便沒有任何Direct Reference,也不會被肅清。不斷要到JVM內存缺乏且沒有Direct Reference時才會肅清,SoftReference是用來設計objct-cache之用的。如此一來SoftReference不但可以把對象cache起來,也不會形成內存缺乏的錯誤(OutOfMemoryError)。
(3)弱援用
假如一個對象只具有弱援用,那該類就是可有可無的對象,由於只需該對象被gc掃描到隨時都會把它干掉。
弱援用和軟援用的區別:只具有弱援用的對象擁有更長久的生命周期。在渣滓回收器線程掃描它所管轄的內存區域的進程中,一旦發現了只具有弱援用的對象,不論以後內存空間足夠與否,都會回收它的內存。不過,由於渣滓回收器是一個優先級很低的線程,因而不一定會很快發現只具有弱援用的對象。
弱援用可以和一個援用隊列(ReferenceQueue)結合運用,假如弱援用所援用的對象呗渣滓回收器回收,Java虛擬機就會把這個弱援用加到與之關聯的援用隊列中。
(4)虛援用
“虛援用”與其他集中援用不同,虛援用並不決議對象的生命周期。假如一個對象僅持有虛援用,那麼它就和沒有任何援用一樣,在任何時分都能夠被渣滓回收器回收。虛援用次要用來跟蹤對象被渣滓回收器回收的活動。
虛援用與軟援用和弱援用的區別:虛援用必需和援用隊列(ReferneceQueue)結合運用。當渣滓回收器預備回收一個對象時,假如發現它還是虛援用,就會在回收對象的內存之前,把這個虛援用假設到與之關聯的援用隊列中。順序可以經過判別援用隊列中能否參加了虛援用。來理解被援用的對象能否要被渣滓回收。順序假如發現某個虛援用曾經被參加到援用隊列,那麼就可以在援用的對象的內存被回收之前采用必要的舉動。
樹立虛援用之後經過get辦法前往後果一直為null,經過源代碼會發現,虛援用通常會把援用的對象寫進referent,只是get辦法前往後果為null。和gc交互的進程:a.不把referent設置為null,直接把heap中的new String(“abc”)對象設置為可完畢的(finalizable)。b.與軟援用和弱援用不同,先把PhantomReference對象添加到它的ReferencQueue中,然後在釋放虛可及的對象。
10.Java的類加載器
10.1.Java的類加載器的品種都有哪些?
(1)根類加載器(Bootstrap)---C++寫的,看不到源碼
(2)擴展類加載器(Extension)---加載地位:jre\lib\ext中
(3)零碎(使用)類加載器(System\App)---加載地位:classpath中
(4)自定義加載器(必需承繼ClassLoader)
10.2.類什麼時分被初始化?
(1)創立類的實例,也就是new一個對象。
(2)訪問某個類或接口的靜態變量,或許對該靜態變量賦值。
(3)調用類的靜態辦法。
(4)反射。
(5)初始化一個類的子類。
(6)JVM啟動時標明的啟動類,即文件名和類名相反的那個類。
只要這6種狀況才會招致類的初始化。
10.3.類的初始化步驟
(1)假如這個類還沒有被加載和鏈接,那先停止加載和鏈接。
(2)假設這個類存在直接父類,並且這個類還沒有被初始化(留意:在一個類加載器中,類智能初始化一次),那就初始化直接的父類(不適用於接口)。
(3)假設類中存在初始化語句(如static變量和static塊),那就順次執行這些初始化語句。