面向過程與面向?qū)ο蟮膮^(qū)別:
面向過程性能比面向?qū)ο笮阅芨?但是不容易維護,不容易調(diào)用,也不容易擴展
面向?qū)ο笮阅鼙容^低,但是易維護,易復(fù)用,也易擴展,有三大特性:多態(tài),繼承,封裝,所以能夠降低耦合
JVM
JVM是運行java字節(jié)碼的虛擬機,在不同的操作系統(tǒng)都會都各自的虛擬機,所以java之所以這么強大就是因為可以一次編譯處處運行,什么是字節(jié)碼呢,字節(jié)碼就是計算機能都讀懂的代碼
程序代碼到運行的步驟
java代碼通過jdk的javac編譯獲得字節(jié)碼文件,通過虛擬機加載字節(jié)碼文件執(zhí)行程序
JDK是java開發(fā)工具,內(nèi)含jre可以創(chuàng)建和編輯程序,jre是Java運行環(huán)境,jre包含jvmjava類庫等,不能創(chuàng)建新程序
java面向?qū)ο缶幊倘筇卣?/h1>封裝,繼承,多態(tài)
封裝:把一個類的屬性私有化,同時提供外面訪問屬性的方法
繼承:擁有父類所有的屬性和方法,但是只能訪問父類允許的方法和屬性
多態(tài):
String、StringBuilder、StringBuffer
String是不可變字符串,每次操作String都會創(chuàng)建新的string對象,StringBuilder和StringBuffer都繼承abstractStringBuilder,每次操作上面兩個對象都是在自身基礎(chǔ)上操作的,且StringBuffer對方法加了同步鎖,線程安全,StringBuilder線程不安全,所以StringBuilder性能會不StringBuffer性能高. String是由final修飾的字符數(shù)組來保存字符串的,所以String不可變,StringBuffer和StringBuilder是由字符數(shù)組來保存字符串的所以兩種對象是可變的
裝箱和拆箱
裝箱:將基本類型用對應(yīng)的引用類型包裝起來
拆箱:將包裝類型轉(zhuǎn)換成基本數(shù)據(jù)類型
為什么要定義一個無參構(gòu)造器
在執(zhí)行子類構(gòu)造方法之前如果沒調(diào)用super(來調(diào)用父類特定的構(gòu)造方法),則會調(diào)用無參構(gòu)造方法,所以如果沒有定義一個無參構(gòu)造器的話且沒有用super來調(diào)用特定的構(gòu)造方法就會編譯錯誤
接口和抽象類的區(qū)別是什么
接口默認(rèn)是public 所有方法在接口中不能有實現(xiàn)方法,抽象方法可以有其他非抽象方法
一個類可以繼承多個接口,但是只能實現(xiàn)一個抽象類
接口默認(rèn)public修飾,抽象類除了private不能修飾其他都可以修飾
成員變量和局部變量有什么區(qū)別
成員變量定義在類中方法外,局部變量是定義在方法中,在內(nèi)存空間中,成員變量是存在堆中,局部變量是存在棧中.成員變量的生命周期是伴隨著對象的創(chuàng)建而存在的,伴隨對象銷毀而銷毀,而局部變量是在方法被調(diào)用時而存在的,方法調(diào)用完畢而銷毀
一個類的構(gòu)造方法的作用
構(gòu)造方法是初始化對象,每個類都會有一個默認(rèn)的無參構(gòu)造器
構(gòu)造方法有哪些特征
構(gòu)造名與類名相同,沒有返回值但是不能用void來修飾
hashCode和equals
就比如往hashSet集合中存放對象時,會先調(diào)用hashcode方法來計算hash值,如果不相等的就說明不存在可以存,如果相同的話就調(diào)用equals方法比較兩個對象是否相等,如果相等不存,不相等就存
線程的基本狀態(tài)
初始狀態(tài),線程被創(chuàng)建,但是沒有調(diào)用start()方法
運行狀態(tài)
阻塞狀態(tài)
等待狀態(tài)
超時等待狀態(tài)
終止?fàn)顟B(tài)
當(dāng)線程被創(chuàng)建后調(diào)用start()方法后就進入就緒狀態(tài),等待獲取cpu的時間片,然后進入運行狀態(tài),調(diào)用wait()方法進入等待狀態(tài),調(diào)用sleep()進入超時等待狀態(tài),當(dāng)超時時間達(dá)到后就會重新進入運行狀態(tài),當(dāng)線程調(diào)用同步鎖后就會進入阻塞狀態(tài),只有執(zhí)行完當(dāng)前縣城后才會重新回到運行狀態(tài)
final關(guān)鍵字
final修飾的變量必須要初始化后才能使用,且初始化后不能再改變
final修飾的方法不能被重載
final修飾的類不能被繼承
IO流常見的流
字符流/字節(jié)流
BIO和NIO的區(qū)別
BIO是阻塞IO,當(dāng)一個請求過來,要接收數(shù)據(jù),都會先開啟Socket,然后開啟一個線程,讀取數(shù)據(jù),返回結(jié)果,只有業(yè)務(wù)完成后線程才能釋放線程,當(dāng)大量的請求進來后都會進去阻塞狀態(tài)
NIO是非阻塞IO,當(dāng)每一個請求進來后,都會創(chuàng)建一個通道,一個selector會監(jiān)聽多個通道的方式,當(dāng)通道的狀態(tài)為就緒狀態(tài)時就會開啟一個線程,執(zhí)行多路復(fù)用操作
final、finally、finalize
finally是異常處理的一部分,只能用在try/cath語句中,表示最后一句要執(zhí)行
finalize,對象被回收的時候會被調(diào)用,在垃圾收集器刪除對象之前會被調(diào)用
ArraysList擴容機制
ArraysList的默認(rèn)長度為10,當(dāng)調(diào)用add方法的時候,會對ArrayList的長度進行改變,當(dāng)往list存儲的元素長度大于默認(rèn)長度時就會對原素組的長度+1后進行擴容1.5倍,然后在判斷新數(shù)組的長度是否足夠,夠了就用這個長度創(chuàng)建一個新的數(shù)組,不夠?qū)?shù)組長度設(shè)置為需要的長度,再將原數(shù)組復(fù)制到新數(shù)組
ArraysList,LinkedList,Vector的區(qū)別
ArrayList和Vector都是底層通過數(shù)組實現(xiàn)的,可以通過索引查詢元素,但是修改數(shù)組后需要重新創(chuàng)建新的數(shù)組并且將修改后的數(shù)組復(fù)制到新數(shù)組,比較麻煩,Vector底層是通過鏈表來實現(xiàn)的,提供了雙向鏈表存儲功能,所以查詢元素是需要遍歷,但是插入數(shù)據(jù)只需要記錄前后元素即可,插入數(shù)據(jù)比較方便
ArraysList和Vector:ArrayList線程不安全,Vector方法加了同步鎖所以線程安全,但是性能就會降低,ArrayList
ArraysList的擴容是在原數(shù)組長度+1后的1.5倍,Vector是在原數(shù)組長度+1后的2倍
深拷貝和淺拷貝的區(qū)別
淺拷貝:復(fù)制內(nèi)存地址,被復(fù)制的對象發(fā)生改變,復(fù)制的對象也會跟著改變
深拷貝:在內(nèi)存中新開辟一個新的空間用于存儲拷貝的對象
序列化和反序列化
序列化就是將對象轉(zhuǎn)換成字節(jié)序列也就是比較常見的變成文件
反序列化就是將字節(jié)序列化轉(zhuǎn)變成對象
怎么實現(xiàn)序列化
實現(xiàn)Serializable接口即可
如果不想字段被序列化怎么處理
使用transient關(guān)鍵字修飾即可
HashMap底層原理
HashMap是基于Map接口實現(xiàn)的,以鍵值對的形式存儲數(shù)據(jù),底層是由數(shù)組,鏈表和黑紅樹數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的,三種結(jié)構(gòu)結(jié)合使用可以取其精華,數(shù)組查詢效率高,鏈表增刪改效率高,當(dāng)鏈表元素超過8個的時候就會用紅黑樹代替鏈表,因為紅黑樹是二叉平衡數(shù),所以查詢效率會比鏈表高,HashMAp的初始容量為16,擴容是原長度的2倍
HashMap,HashTable和ConcurrentHashMap的區(qū)別
HashMap的線程不安全,接收一個空的key和空的value,異步執(zhí)行,快速失敗迭代器,在遍歷的過程中有其他線程操作增刪操作的時候會拋出異常,因為迭代器操作的是集合本身
HashTable線程安全,key和value不能為空,同步執(zhí)行,在遍歷是其他線程進行增刪操作的時候不會拋出異常,因為迭代器操作的是原集合的拷貝
HashMap在jdk1.8后當(dāng)鏈表長度大于8個是紅黑樹就會替換鏈表結(jié)構(gòu)
HashTable和ConcurrentHashMap的區(qū)別,ConcurrentHashMap是在HashTable上優(yōu)化的,優(yōu)化了鏈表的查詢修改的效率,因為HashTable的是鎖住整個Map,而ConcurrentHashMap只鎖了一部分Map,所以效率有所提高
為什么HashMap存儲數(shù)據(jù)的容量會采用二進制
因為為了HashMap的存取效率高,要經(jīng)量減少碰撞,就要經(jīng)量把數(shù)據(jù)分配均勻,而取模運算就很好符合這個需求,所以存儲容量會采用二進制
HashMap集合中put是如何實現(xiàn)的
調(diào)用put方法是首先判斷數(shù)組是否為空,如果為空的話先進行擴容,然后再根據(jù)key計算出hash值得到插入的數(shù)組索引,如果索引所在的元素是空的話就直接插入元素然后判斷已存的鍵值對數(shù)是否超過最大容量,如果超過就要進行擴容.如果索引所在的元素不為空的話比較數(shù)組的元素與key是否相同,如果相同直接覆蓋,不相同的話判斷元素是否為紅黑樹,如果數(shù)紅黑樹的話直接插入數(shù)據(jù)即可,如果不是的話,判斷鏈表長度是否大于8,如果沒大于的話直接遍歷鏈表插入,如果遍歷過程中發(fā)現(xiàn)key已經(jīng)存在就直接覆蓋,如果是紅黑數(shù)的話直接樹中插入鍵值對