想了解一下學(xué)Java的小伙伴們触趴,在學(xué)習(xí)Java的時(shí)候有沒有去總結(jié)知識(shí)點(diǎn)氮发,哪些知識(shí)點(diǎn)我們沒有掌握,哪些知識(shí)點(diǎn)是我們還沒有掌握的冗懦,今天小編來(lái)發(fā)掘一些Java基礎(chǔ)面試知識(shí)點(diǎn)爽冕,不知道大家掌握沒有。
小編分享的一些知識(shí)點(diǎn)披蕉,都是一些經(jīng)驗(yàn)的總結(jié)颈畸,踩過坑的乌奇,可能不是很全面,還請(qǐng)各位讀者多多指教與反饋眯娱。
Java基礎(chǔ)學(xué)習(xí)總結(jié)
每部分內(nèi)容會(huì)重點(diǎn)寫一些常見知識(shí)點(diǎn)礁苗,方便復(fù)習(xí)和記憶,但是并不是全部?jī)?nèi)容困乒,詳細(xì)的內(nèi)容請(qǐng)參見具體的文章地址寂屏。
面向?qū)ο笕筇匦?/p>
繼承:一般類只能單繼承贰谣,內(nèi)部類實(shí)現(xiàn)多繼承娜搂,接口可以多繼承
封裝:訪問權(quán)限控制public > protected > 包 > private 內(nèi)部類也是一種封裝
多態(tài):編譯時(shí)多態(tài),體現(xiàn)在向上轉(zhuǎn)型和向下轉(zhuǎn)型吱抚,通過引用類型判斷調(diào)用哪個(gè)方法(靜態(tài)分派)百宇。
運(yùn)行時(shí)多態(tài),體現(xiàn)在同名函數(shù)通過不同參數(shù)實(shí)現(xiàn)多種方法(動(dòng)態(tài)分派)秘豹。
基本數(shù)據(jù)類型
基本類型位數(shù)携御,自動(dòng)裝箱,常量池
例如byte類型是1byte也就是8位既绕,可以表示的數(shù)字是-128到127啄刹,因?yàn)檫€有一個(gè)0,加起來(lái)一共是256凄贩,也就是2的八次方誓军。
32位和64位機(jī)器的int是4個(gè)字節(jié)也就是32位,char是1個(gè)字節(jié)就是8位疲扎,float是4個(gè)字節(jié)昵时,double是8個(gè)字節(jié),long是8個(gè)字節(jié)椒丧。
所以它們占有字節(jié)數(shù)是相同的壹甥,這樣的話兩個(gè)版本才可以更好地兼容。(應(yīng)該)
基本數(shù)據(jù)類型的包裝類只在數(shù)字范圍-128到127中用到常量池壶熏,會(huì)自動(dòng)拆箱裝箱句柠,其余數(shù)字范圍的包裝類則會(huì)新建實(shí)例
String及包裝類
String類型是final類型,在堆中分配空間后內(nèi)存地址不可變棒假。
底層是final修飾的char數(shù)組俄占,數(shù)組的內(nèi)存地址同樣不可變。
但實(shí)際上可以通過修改char[n] = 'a'來(lái)進(jìn)行修改淆衷,不會(huì)改變String實(shí)例的內(nèi)存值缸榄,不過在jdk中,用戶無(wú)法直接獲取char祝拯,也沒有方法能操作該數(shù)組甚带。
所以String類型的不可變實(shí)際上也是理論上的不可變她肯。所以我們?cè)诜峙銼tring對(duì)象以后,如果將其 = "abc"鹰贵,那也只是改變了引用的指向晴氨,實(shí)際上沒有改變?cè)瓉?lái)的對(duì)象。
StringBuffer和StringBuilder底層是可變的char數(shù)組碉输,繼承父類AbstractStringBuilder的各種成員和方法籽前,實(shí)際上的操作都是由父類方法來(lái)完成的。
final關(guān)鍵字
final修飾基本數(shù)據(jù)類型保證不可變
final修飾引用保證引用不能指向別的對(duì)象敷钾,否則會(huì)報(bào)錯(cuò)枝哄。
final修飾類,類的實(shí)例分配空間后地址不可變阻荒,子類不能重寫所有父類方法挠锥。因此在cglib動(dòng)態(tài)代理中,不能為一個(gè)類的final修飾的函數(shù)做代理侨赡,因?yàn)閏glib要將被代理的類設(shè)置為父類蓖租,然后再生成字節(jié)碼。
final修飾方法羊壹,子類不能重寫該方法蓖宦。
抽象類和接口
1 抽象類可以有方法實(shí)現(xiàn)。
抽象類可以有非final成員變量油猫。
抽象方法要用abstract修飾稠茂。
抽象類可以有構(gòu)造方法,但是只能由子類進(jìn)行實(shí)例化眨攘。
2 接口可以用extends加多個(gè)接口實(shí)現(xiàn)多繼承主慰。
接口只能有public final類型的成員變量。
接口只能有抽象方法鲫售,不能有方法體共螺、
接口不能實(shí)例化,但是可以作為引用類型情竹。
代碼塊和加載順序
假設(shè)該類是第一次進(jìn)行實(shí)例化藐不。那么有如下加載順序
靜態(tài)總是比非靜態(tài)優(yōu)先,從早到晚的順序是:
1 靜態(tài)代碼塊 和 靜態(tài)成員變量的順序根據(jù)代碼位置前后來(lái)決定秦效。
2 代碼塊和成員變量的順序也根據(jù)代碼位置來(lái)決定
3 最后才調(diào)用構(gòu)造方法構(gòu)造方法
包雏蛮、內(nèi)部類、外部類
1 Java項(xiàng)目一般從src目錄開始有com.*.*.A.java這樣的目錄結(jié)構(gòu)阱州。這就是包結(jié)構(gòu)挑秉。所以一般編譯后的結(jié)構(gòu)是跟包結(jié)構(gòu)一模一樣的,這樣的結(jié)構(gòu)保證了import時(shí)能找到正確的class引用包訪問權(quán)限就是指同包下的類可見苔货。
import 一般加上全路徑犀概,并且使用.*時(shí)只包含當(dāng)前目錄的所有類文件立哑,不包括子目錄。
2 外部類只有public和default兩種修飾姻灶,要么全局可訪問铛绰,要么包內(nèi)可訪問。
3 內(nèi)部類可以有全部訪問權(quán)限产喉,因?yàn)樗母拍罹褪且粋€(gè)成員變量捂掰,所以訪問權(quán)限設(shè)置與一般的成員變量相同。
非靜態(tài)內(nèi)部類是外部類的一個(gè)成員變量曾沈,只跟外部類的實(shí)例有關(guān)这嚣。
靜態(tài)內(nèi)部類是獨(dú)立于外部類存在的一個(gè)類,與外部類實(shí)例無(wú)關(guān)晦譬,可以通過外部類.內(nèi)部類直接獲取Class類型疤苹。
異常
1 異常體系的最上層是Throwable類
子類有Error和Exception
Exception的子類又有RuntimeException和其他具體的可檢查異常互广。
2 Error是jvm完全無(wú)法處理的系統(tǒng)錯(cuò)誤敛腌,只能終止運(yùn)行。
運(yùn)行時(shí)異常指的是編譯正確但運(yùn)行錯(cuò)誤的異常惫皱,如數(shù)組越界異常像樊,一般是人為失誤導(dǎo)致的,這種異常不用try catch旅敷,而是需要程序員自己檢查生棍。
可檢查異常一般是jvm處理不了的一些異常,但是又經(jīng)常會(huì)發(fā)生媳谁,比如Ioexception涂滴,Sqlexception等,是外部實(shí)現(xiàn)帶來(lái)的異常晴音。
3 多線程的異常流程是獨(dú)立的柔纵,互不影響。
大型模塊的子模塊異常一般需要重新封裝成外部異常再次拋出锤躁,否則只能看到最外層異常信息搁料,難以進(jìn)行調(diào)試。
日志框架是異常報(bào)告的最好幫手系羞,log4j郭计,slf4j中,在工作中必不可少椒振。
泛型
Java中的泛型是偽泛型昭伸,只在編譯期生效,運(yùn)行期自動(dòng)進(jìn)行泛型擦除澎迎,將泛型替換為實(shí)際上傳入的類型庐杨。
泛型類用class <T> A {
}這樣的形式表示宋下,里面的方法和成員變量都可以用T來(lái)表示類型。泛型接口也是類似的辑莫,不過泛型類實(shí)現(xiàn)泛型接口時(shí)可以選擇注入實(shí)際類型或者是繼續(xù)使用泛型学歧。
泛型方法可以自帶泛型比如void <E> E go;
泛型可以使用?通配符進(jìn)行泛化 Object<?>可以接受任何類型
也可以使用 <??extends?Number> <? super Integer>這種方式進(jìn)行上下邊界的限制。
Class類和Object類
Java反射的基礎(chǔ)是Class類各吨,該類封裝所有其他類的類型信息枝笨,并且在每個(gè)類加載后在堆區(qū)生成每個(gè)類的一個(gè)Class<類名>實(shí)例,用于該類的實(shí)例化揭蜒。
Java中可以通過多種方式獲取Class類型横浑,比如A.class,new?A.getClass方法以及Class.forName("com.?.?.A")方法。
Object是所有類的父類屉更,有著自己的一些私有方法徙融,以及被所有類繼承的9大方法。
有人討論Object和Class類型誰(shuí)先加載誰(shuí)后加載瑰谜,因?yàn)槊總€(gè)類都要繼承Object欺冀,但是又得先被加載到堆區(qū),事實(shí)上萨脑,這個(gè)問題在JVM初始化時(shí)就解決了隐轩,沒必要多想。
javac和java
javac?是編譯一個(gè)java文件的基本命令渤早,通過不同參數(shù)可以完成各種配置职车,比如導(dǎo)入其他類,指定編譯路徑等鹊杖。
java是執(zhí)行一個(gè)java文件的基本命令悴灵,通過參數(shù)配置可以以不同方式執(zhí)行一個(gè)java程序或者是一個(gè)jar包。
javap是一個(gè)class文件的反編譯程序骂蓖,可以獲取class文件的反編譯結(jié)果积瞒,甚至是jvm執(zhí)行程序的每一步代碼實(shí)現(xiàn)。
反射
Java反射包reflection提供對(duì)Class涯竟,Method赡鲜,field,constructor等信息的封裝類型庐船。
通過這些api可以輕易獲得一個(gè)類的各種信息并且可以進(jìn)行實(shí)例化银酬,方法調(diào)用等。
類中的private參數(shù)可以通過setaccessible方法強(qiáng)制獲取筐钟。
反射的作用可謂是博大精深揩瞪,JDK動(dòng)態(tài)代理生成代理類的字節(jié)碼后,首先把這個(gè)類通過defineclass定義成一個(gè)類篓冲,然后用class.for(name)會(huì)把該類加載到j(luò)vm李破,之后我們就可以通過宠哄,A.class.GetMethod獲取其方法,然后通過invoke調(diào)用其方法嗤攻,在調(diào)用這個(gè)方法時(shí)毛嫉,實(shí)際上會(huì)通過被代理類的引用再去調(diào)用原方法。
枚舉類
枚舉類繼承Enum并且每個(gè)枚舉類的實(shí)例都是唯一的妇菱。
枚舉類可以用于封裝一組常量承粤,取值從這組常量中取,比如一周的七天闯团,一年的十二個(gè)月辛臊。
枚舉類的底層實(shí)現(xiàn)其實(shí)是語(yǔ)法糖,每個(gè)實(shí)例可以被轉(zhuǎn)化成內(nèi)部類房交。并且使用靜態(tài)代碼塊進(jìn)行初始化彻舰,同時(shí)保證內(nèi)部成員變量不可變。
序列化
序列化的類要實(shí)現(xiàn)serializable接口
transient修飾符可以保證某個(gè)成員變量不被序列化
readObject和writeOject來(lái)實(shí)現(xiàn)實(shí)例的寫入和讀取候味。
待更新刃唤。
事實(shí)上,一些擁有數(shù)組變量的類都會(huì)把數(shù)組設(shè)為transient修飾负溪,這樣的話不會(huì)對(duì)整個(gè)數(shù)組進(jìn)行序列化透揣,而是利用專門的方法將有數(shù)據(jù)的數(shù)組范圍進(jìn)行序列化济炎,以便節(jié)省空間川抡。
動(dòng)態(tài)代理
jdk自帶的動(dòng)態(tài)代理可以代理一個(gè)已經(jīng)實(shí)現(xiàn)接口的類。
cglib代理可以代理一個(gè)普通的類须尚。
動(dòng)態(tài)代理的基本實(shí)現(xiàn)原理都是通過字節(jié)碼框架動(dòng)態(tài)生成字節(jié)碼崖堤,并且在用defineclass加載類后,獲取代理類的實(shí)例耐床。
一般需要實(shí)現(xiàn)一個(gè)代理處理器密幔,用來(lái)處理被代理類的前置操作和后置操作。在JDK動(dòng)態(tài)代理中撩轰,這個(gè)類叫做invocationHandler胯甩。
JDK動(dòng)態(tài)代理首先獲取被代理類的方法,并且只獲取在接口中聲明的方法堪嫂,生成代理類的字節(jié)碼后偎箫,首先把這個(gè)類通過defineclass定義成一個(gè)類,然后把該類加載到j(luò)vm皆串,之后我們就可以通過淹办,A.class.GetMethod獲取其方法,然后通過invoke調(diào)用其方法恶复,在調(diào)用這個(gè)方法時(shí)怜森,實(shí)際上會(huì)通過被代理類的引用再去調(diào)用原方法速挑。
而對(duì)于cglib動(dòng)態(tài)代理,一般會(huì)把被代理類設(shè)為代理類的父類副硅,然后獲取被代理類中所有非final的方法姥宝,通過asm字節(jié)碼框架生成代理類的字節(jié)碼,這個(gè)代理類很神奇恐疲,他會(huì)保留原來(lái)的方法以及代理后的方法伶授,通過方法數(shù)組的形式保存。
cglib的動(dòng)態(tài)代理需要實(shí)現(xiàn)一個(gè)enhancer和一個(gè)interceptor流纹,在interceptor中配置我們需要的代理內(nèi)容糜烹。如果沒有配置interceptor,那么代理類會(huì)調(diào)用被代理類自己的方法漱凝,如果配置了interceptor疮蹦,則會(huì)使用代理類修飾過的方法。
多線程
這里先不講juc包里的多線程類茸炒。juc相關(guān)內(nèi)容會(huì)在Java并發(fā)專題講解愕乎。
線程的實(shí)現(xiàn)可以通過繼承Thread類和實(shí)現(xiàn)Runable接口
也可以使用線程池。callable配合future可以實(shí)現(xiàn)線程中的數(shù)據(jù)獲取壁公。
Java中的線程有7種狀態(tài)感论,new?runable running blocked waiting time_waiting terminate
blocked是線程等待其他線程鎖釋放。
waiting是wait以后線程無(wú)限等待其他線程使用notify喚醒
time_wating是有限時(shí)間地等待被喚醒紊册,也可能是sleep固定時(shí)間比肄。
Thread的join是實(shí)例方法,比如a.join(b),則說明a線程要等b線程運(yùn)行完才會(huì)運(yùn)行囊陡。
o.wait方法會(huì)讓持有該對(duì)象o的線程釋放鎖并且進(jìn)入阻塞狀態(tài)芳绩,notify則是持有o鎖對(duì)象的線程通知其他等待鎖的線程獲取鎖。notify方法并不會(huì)釋放鎖撞反。注意這兩個(gè)方法都只能在synchronized同步方法或同步塊里使用妥色。
synchronized方法底層使用系統(tǒng)調(diào)用的mutex鎖,開銷較大遏片,jvm會(huì)為每個(gè)鎖對(duì)象維護(hù)一個(gè)等待隊(duì)列嘹害,讓等待該對(duì)象鎖的線程在這個(gè)隊(duì)列中等待。當(dāng)線程獲取不到鎖時(shí)則讓線程阻塞吮便,而其他檢查notify以后則會(huì)通知任意一個(gè)線程笔呀,所以這個(gè)鎖時(shí)非公平鎖。
Thread.sleep线衫,Thread.interrupt等方法都是類方法凿可,表示當(dāng)前調(diào)用該方法的線程的操作。
一個(gè)線程實(shí)例連續(xù)start兩次會(huì)拋異常,這是因?yàn)榫€程start后會(huì)設(shè)置標(biāo)識(shí),如果再次start則判斷為錯(cuò)誤枯跑。
IO流
IO流也是Java中比較重要的一塊惨驶,Java中主要有字節(jié)流,字符流敛助,文件等粗卜。其中文件也是通過流的方式打開,讀取和寫入的纳击。
IO流的很多接口都使用了裝飾者模式续扔,即將原類型通過傳入裝飾類構(gòu)造函數(shù)的方式,增強(qiáng)原類型焕数,以此獲得像帶有緩沖區(qū)的字節(jié)流纱昧,或者將字節(jié)流封裝成字符流等等,其中需要注意的是編碼問題堡赔,后者打印出來(lái)的結(jié)果可能是亂碼哦识脆。
IO流與網(wǎng)絡(luò)編程息息相關(guān),一個(gè)socket接入后善已,我們可以獲取它的輸入流和輸出流灼捂,以獲取TCP數(shù)據(jù)包的內(nèi)容,并且可以往數(shù)據(jù)報(bào)里寫入內(nèi)容换团,因?yàn)門CP協(xié)議也是按照流的方式進(jìn)行傳輸?shù)南こ恚瑢?shí)際上TCP會(huì)將這些數(shù)據(jù)進(jìn)行分包處理,并且通過差錯(cuò)檢驗(yàn)艘包,超時(shí)重傳的猛,滑動(dòng)窗口協(xié)議等方式,保證了TCP數(shù)據(jù)包的高效和可靠傳輸辑甜。
網(wǎng)絡(luò)編程
承接IO流的內(nèi)容
IO流與網(wǎng)絡(luò)編程息息相關(guān)衰絮,一個(gè)socket接入后,我們可以獲取它的輸入流和輸出流磷醋,以獲取TCP數(shù)據(jù)包的內(nèi)容,并且可以往數(shù)據(jù)報(bào)里寫入內(nèi)容胡诗,因?yàn)門CP協(xié)議也是按照流的方式進(jìn)行傳輸?shù)牡讼撸瑢?shí)際上TCP會(huì)將這些數(shù)據(jù)進(jìn)行分包處理,并且通過差錯(cuò)檢驗(yàn)煌恢,超時(shí)重傳骇陈,滑動(dòng)窗口協(xié)議等方式,保證了TCP數(shù)據(jù)包的高效和可靠傳輸瑰抵。
除了使用socket來(lái)獲取TCP數(shù)據(jù)包外你雌,還可以使用UDP的DatagramPacket來(lái)封裝UDP數(shù)據(jù)包,因?yàn)閁DP數(shù)據(jù)包的大小是確定的,所以不是使用流方式處理婿崭,而是需要事先定義他的長(zhǎng)度拨拓,源端口和目標(biāo)端口等信息。
為了方便網(wǎng)絡(luò)編程氓栈,Java提供了一系列類型來(lái)支持網(wǎng)絡(luò)編程的api渣磷,比如URL類,InetAddress類等授瘦。
Java8
接口中的默認(rèn)方法醋界,接口終于可以有方法實(shí)現(xiàn)了,使用注解即可標(biāo)識(shí)出默認(rèn)方法提完。
lambda表達(dá)式實(shí)現(xiàn)了函數(shù)式編程形纺,通過注解可以聲明一個(gè)函數(shù)式接口,該接口中只能有一個(gè)方法徒欣,這個(gè)方法正是使用lambda表達(dá)式時(shí)會(huì)調(diào)用到的接口挡篓。
Option類實(shí)現(xiàn)了非空檢驗(yàn)
新的日期API
各種api的更新,包括chm,hashmap的實(shí)現(xiàn)等
Stream流概念瞬内,實(shí)現(xiàn)了集合類的流式訪問丛肢,可以基于此使用map和reduce并行計(jì)算。
? ? ? ?為了讓學(xué)習(xí)變得輕松戏羽、高效,今天給大家免費(fèi)分享一套Java入門教學(xué)資源楼吃。幫助大家在成為Java架構(gòu)師的道路上披荊斬棘始花。需要入門的資料歡迎加入學(xué)習(xí)交流群:9285,05736