新手初學(xué)Java基礎(chǔ)
1.Java的基本數(shù)據(jù)類型有哪些?
2.如何理解面向?qū)ο蠛兔嫦蜻^(guò)程?
面向過(guò)程:就是分析出解決問(wèn)題所需要的步驟,然后用函數(shù)把這些步驟一步一步實(shí)現(xiàn),使用的時(shí)候一個(gè)一個(gè)依次調(diào)用就可以了。是一種思考問(wèn)題的基礎(chǔ)方法。
面向?qū)ο螅菏前褬?gòu)成問(wèn)題事務(wù)分解成各個(gè)對(duì)象,建立對(duì)象的目的不是為了完成一個(gè)步驟,而是為了描敘某個(gè)事物在整個(gè)解決問(wèn)題的步驟中的行為。
面向?qū)ο蟮乃拇筇卣鳎?/strong>
- 封裝 :繼承是從已有類得到繼承信息創(chuàng)建新類的過(guò)程
- 繼承 :通常認(rèn)為封裝是把數(shù)據(jù)和操作數(shù)據(jù)的方法綁定起來(lái),對(duì)數(shù)據(jù)的訪問(wèn)只能通過(guò)已定義的接口
- 多態(tài) :多態(tài)性是指允許不同子類型的對(duì)象對(duì)同一消息作出不同的響應(yīng)
- 抽象 :是將一類對(duì)象的共同特征總結(jié)出來(lái)構(gòu)造類的過(guò)程,包括數(shù)據(jù)抽象行為和行為抽象兩方面
面向過(guò)程
- 去菜市場(chǎng)買五花肉
- 洗凈、切塊、準(zhǔn)備作料等備用
- 下鍋、上色、翻炒、燉
- 出鍋
面向?qū)ο?/strong>
- 五花肉備好
- 五花肉下鍋
- 五花肉出鍋
3.如何理解多態(tài)
父類引用指向子類的實(shí)例:例如:
List<Object> list = new ArrayList<>();
4、封裝舉例?
實(shí)體類的封裝,將屬性私有,只有本類能訪問(wèn),如此就對(duì)信息進(jìn)行的隱藏。對(duì)每個(gè)值屬性提供對(duì)外的公共方法訪問(wèn),也就是創(chuàng)建一對(duì)賦取值方法,用于對(duì)私有屬性的訪問(wèn)
5、繼承?
Java是單繼承的,子類從父類繼承方法,使得子類具有父類相同的行為
6、char可不可以存儲(chǔ)一個(gè)中文漢字,為什么?
char型變量是用來(lái)存儲(chǔ)Unicode編碼的字符的,unicode編碼字符集中包含漢字,所以可以存儲(chǔ),有些特殊的漢字沒(méi)有包含在Unicode中,就不能存儲(chǔ)了,Unicode編碼占用兩個(gè)字節(jié),所以,char類型的變量也是占用兩個(gè)字節(jié)
7、自動(dòng)拆裝箱?int和integer有什么區(qū)別?
裝箱:將基本數(shù)據(jù)類型轉(zhuǎn)換為包裝類對(duì)象
拆箱:將包裝類對(duì)象轉(zhuǎn)換成基本類型的值
裝箱使用包裝器的valueOf方法,拆箱使用包裝器的intValue方法。
為什么要引入自動(dòng)拆裝箱?主要用于Java的集合中,集合類型只能指定包裝類,List
list = new Arraylist<>();
原理?Java編譯器的語(yǔ)法糖。
語(yǔ)法糖 Syntactic Sugar 糖衣語(yǔ)法,方便開(kāi)發(fā)人員使用,JVM并不識(shí)在編譯階段解語(yǔ)法糖,還原為基礎(chǔ)語(yǔ)法
public static void main(String[] args) { Integer a = 127; Integer b = 127; Integer c = 128; Integer d = 128; System.out.println(a == b); // true System.out.println(c == d); // false } java中基本類型的包裝類的大部分都實(shí)現(xiàn)了常量池技術(shù),這些類是Byte,Short,Integer,Long,Character,Boolean,另外兩種浮點(diǎn)數(shù)類型的包裝類則沒(méi)有實(shí)現(xiàn)。另外Byte,Short,Integer,Long,Character這5種整型的包裝類也只是在對(duì)應(yīng)值小于等于127時(shí)才可使用對(duì)象池。超過(guò)了就要申請(qǐng)空間創(chuàng)建對(duì)象了
8、 == 和 equals 的區(qū)別?
==
比較基本數(shù)據(jù)類型:比較的是變量的值
比較引用數(shù)據(jù)類型:比較的是地址值
equals
如果沒(méi)重寫(xiě)equals方法比較的是兩個(gè)對(duì)象的地址值
如果重寫(xiě)的了equals方法后我們往往比較的是對(duì)象中的屬性的內(nèi)容
equals沖Object類中繼承過(guò)來(lái)的,默認(rèn)的實(shí)現(xiàn)就是使用==
public boolean equals(Object obj){ return (this==obj) }
9、String可以被繼承嗎?
不能被繼承,因?yàn)镾tring類有final修飾符,而final修飾的類是不能被繼承的
- String類是最常用的類之一,為了效率,禁止被繼承和重寫(xiě)為什么用final修飾?
- 為了安全。String類中有很多調(diào)用底層的本地方法,調(diào)用操作系統(tǒng)的API,如果方法可以重寫(xiě),可能被植入惡意代碼,破壞程序。Java的安全性也體現(xiàn)在這里】
10、String buffer和String Builder的區(qū)別?
1、String buffer
和String builder
中的方法和功能是完全等價(jià)的
2、只是StringBuffer中的方法大都采用了synchronize
關(guān)鍵字進(jìn)行修飾,因此是線程安全的,而StringBuilder
沒(méi)有這個(gè)修飾,可以被認(rèn)為是線程不安全的
3、在單線程的程序下,StringBuilder
效率更快,因?yàn)樗恍枰渔i,不具備多線程安全而StringBuffer
則每次都需要對(duì)鎖進(jìn)行判斷,效率相對(duì)更低
11、final、finally、Finalize有什么區(qū)別?
final:
修飾符(關(guān)鍵字) 有三種用法:修飾類、變量、和方法
,
修飾類時(shí),意味著他不能再派生出新的子類,即不能被繼承,因此它和abstract是反義詞。
修飾變量時(shí),該變量使用中不被改變,必須在聲明時(shí)給定初始值,在引用中只能讀取不可修改,即為常量。
修飾方法時(shí),也同樣只能使用,不能在子類中被重寫(xiě)。
finally:
通常放在try……catch的后面構(gòu)造最終執(zhí)行代碼塊,這就意味著程序無(wú)論正常執(zhí)行還是發(fā)生異常,這里的代碼只要JVM不關(guān)閉都能執(zhí)行,可以將釋放外部資源的代碼寫(xiě)在finally塊中
finalize:
Object類中定義的方法,Java中允許使用finalize()方法在垃圾收集器將對(duì)象從內(nèi)存中清除出去之前做必要的清理工作,這個(gè)方法是由垃圾收集器在銷毀對(duì)象時(shí)調(diào)用的,通過(guò)重寫(xiě)finalize() 方法可以整理系統(tǒng)資源或者執(zhí)行其他清理工作
12、Object中有哪些方法?
(1)protected Object clone()--->
創(chuàng)建并返回此對(duì)象的一個(gè)副本。
(2)boolean equals(Object obj)--->
指示某個(gè)其他對(duì)象是否與此對(duì)象“相等”。
(3)protected void finalize()--->
當(dāng)垃圾回收器確定不存在對(duì)該對(duì)象的更多引用時(shí),由對(duì)象的垃圾回收器調(diào)用此方法。
(4)Class<? extendsObject> getClass()--->
返回一個(gè)對(duì)象的運(yùn)行時(shí)類。
(5)int hashCode()--->
返回該對(duì)象的哈希碼值。
(6)void notify()--->
喚醒在此對(duì)象監(jiān)視器上等待的單個(gè)線程。
(7)void notifyAll()--->
喚醒在此對(duì)象監(jiān)視器上等待的所有線程。
(8)String toString()--->
返回該對(duì)象的字符串表示。
(9)void wait()--->
導(dǎo)致當(dāng)前的線程等待,直到其他線程調(diào)用此對(duì)象的 notify() 方法或 notifyAll() 方法。
void wait(long timeout)--->
導(dǎo)致當(dāng)前的線程等待,直到其他線程調(diào)用此對(duì)象的 notify() 方法或 notifyAll()方法,或者超過(guò)指定的時(shí)間量。
void wait(long timeout, int nanos)--->
導(dǎo)致當(dāng)前的線程等待,直到其他線程調(diào)用此對(duì)象的 notify()
13、集合框架簡(jiǎn)單體系圖
14、ArrayList、LinkedList、Vector的區(qū)別?
ArrayList,LinkedList
和Vector
都繼承自List接口。
ArrayList
和Vector
的底層是動(dòng)態(tài)數(shù)組,LinkedList的底層是雙向鏈表.
ArrayList
和Vector
的區(qū)別就是ArrayList
是線程不安全的,Vector
是線程安全的,Vector
中的方法都是同步方法(synchronized),
所以ArrayList的執(zhí)行效率要高于Vector,它也是用的最廣泛的一種集合。
我們重點(diǎn)比較一下ArrayList和LinkedList的區(qū)別,其實(shí)ArrayList和LinkedList之間的區(qū)別就是數(shù)組和雙向鏈表之間的區(qū)別。
數(shù)組的特點(diǎn):因?yàn)閿?shù)組分配的是一塊連續(xù)的內(nèi)存空間,使用索引來(lái)查找元素是非??焖俚?。但是插入,刪除數(shù)據(jù)性能比較低。
雙向鏈表的特點(diǎn),查詢效率較低,因?yàn)椴樵円粋€(gè)元素需要從頭部或尾部開(kāi)始查詢,挨個(gè)遍歷每一個(gè)元素直到找到所需元素,插入,刪除效率高比如我們刪掉一個(gè)元素直接把它前一個(gè)元素的指針指向它后一個(gè)元素就可以了
15、HashMap源碼分析?
先來(lái)看一下添加元素的過(guò)程,然后再看擴(kuò)容方法。
首先要思考一個(gè)問(wèn)題,既然HashMap是用數(shù)組來(lái)存數(shù)據(jù)的,而數(shù)組的類型是一個(gè)Node節(jié)點(diǎn),而節(jié)點(diǎn)中如果只放key和value,每次添加的時(shí)候就去循環(huán)數(shù)組判斷是否有同樣的key,如果沒(méi)有則添加,有就覆蓋,然后每次根據(jù)key取值的時(shí)候也循環(huán)數(shù)組判斷是否存在該key然后取出對(duì)應(yīng)的value,那么可想而知,當(dāng)數(shù)組中的元素量變成10、100、1000甚至成百上千萬(wàn)的時(shí)候,執(zhí)行效率會(huì)有多低。
(1) 所以我們能想到的,HashMap也能想到,而HashMap是怎么解決這一個(gè)問(wèn)題的呢?
答案是,HashMap會(huì)根據(jù)不同的key計(jì)算出數(shù)組下標(biāo),然后直接把該key存到指定的下標(biāo)位置上,取的時(shí)候也是通過(guò)該key計(jì)算出位置,直接通過(guò)下標(biāo)位置在數(shù)組上取,這樣就不需要去循環(huán)判斷取數(shù)據(jù)了,完美解決上面說(shuō)到的問(wèn)題。我們接著看HashMap是同通過(guò)什么樣的方式計(jì)算出位置呢?
(2)首先我們了解一下Hash是什么?
Hash,一般翻譯做散列、雜湊,或音譯為哈希,是把任意長(zhǎng)度的輸入通過(guò)散列算法變換成固定長(zhǎng)度的輸出,該輸出就是散列值。這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠(yuǎn)小于輸入的空間,不同的輸入可能會(huì)散列成相同的輸出,所以不可能從散列值來(lái)確定唯一的輸入值。簡(jiǎn)單的說(shuō)就是一種將任意長(zhǎng)度的消息壓縮到某一固定長(zhǎng)度的消息摘要的函數(shù)。對(duì)不同的關(guān)鍵字可能得到同一散列地址,即key1≠key2,而key1的哈希值=key2的哈希值,這種現(xiàn)象稱碰撞。(但碰撞的概率是很小的)
(3)所以HashMap會(huì)先獲取到key的哈希值,但是假設(shè)當(dāng)前數(shù)組長(zhǎng)度16,獲取到了hash值之后怎樣才能得到獲取存儲(chǔ)的數(shù)組下標(biāo),并且讓下標(biāo)在0~15之中呢?(肯定不能越界對(duì)吧)
答案是這樣的,我們都知道一個(gè)k1取模k2,結(jié)果肯定不會(huì)大于k2對(duì)吧,而且結(jié)果肯定在0~k2之中,所以HashMap就是這樣來(lái)確定下標(biāo)位置的,不過(guò)是用的另外一種方式計(jì)算,就是:(len - 1) & hash,通過(guò)按位與的方式也能達(dá)到取模的效果,而且計(jì)算速度更快。好了,先小小總結(jié)一下,HashMap首先根據(jù)key值獲取到hash值,然后根據(jù)hash值獲取到存放的數(shù)組位置,但是接下來(lái)又有一個(gè)問(wèn)題了。
(4)如果hash發(fā)生了碰撞,就是不同的key但得到了同一個(gè)hash值,結(jié)果獲得的數(shù)組位置也是同一個(gè),本來(lái)同一個(gè)key是可以直接覆蓋的(因?yàn)閔ashmap本來(lái)就不能存相同的key),可是這兩個(gè)key又不是同一個(gè),肯定不能覆蓋,那應(yīng)該怎么辦呢?
所以,HashMap就加入了鏈表,當(dāng)計(jì)算出key位置之后,發(fā)現(xiàn)該位置上已經(jīng)有一個(gè)元素了,然后就進(jìn)行判斷,如果我這個(gè)key的值和已經(jīng)存在的key值不相等,然后就往改元素后面添加,也就是通過(guò)Node節(jié)點(diǎn)指向下一個(gè)Node節(jié)點(diǎn),此時(shí)該數(shù)組位置上就有一個(gè)包含兩個(gè)node節(jié)點(diǎn)的鏈表了。等于當(dāng)添加元素的時(shí)候,發(fā)現(xiàn)該數(shù)組位置上已經(jīng)有值了,并且當(dāng)前key值與鏈表中的所有key都不相等,就往這個(gè)鏈表中追加。可是現(xiàn)在又有了一個(gè)新的問(wèn)題,一旦某一個(gè)數(shù)組位置上鏈表的長(zhǎng)度越來(lái)越長(zhǎng)之后,是不是又回到了當(dāng)初說(shuō)循環(huán)判斷key值,會(huì)影響的效率問(wèn)題(雖然不是每次存取元素都要循環(huán),但還是可以優(yōu)化呀),所以jdk1.8做了進(jìn)一步的優(yōu)化。
所以就增加了紅黑樹(shù)的概念,當(dāng)鏈表中的長(zhǎng)度為9的時(shí)候就轉(zhuǎn)為紅黑樹(shù),使用紅黑樹(shù)結(jié)構(gòu)可以優(yōu)化計(jì)算機(jī)的處理過(guò)程,使得進(jìn)一步的提升了極端情況下的性能。(有部分博客可能沒(méi)有把最初的那個(gè)node節(jié)點(diǎn)計(jì)算進(jìn)來(lái),寫(xiě)著當(dāng)有8次碰撞的時(shí)候轉(zhuǎn)紅黑樹(shù),導(dǎo)致有些人認(rèn)為鏈表中長(zhǎng)度為8的時(shí)候轉(zhuǎn)紅黑樹(shù)
16、HashMap在JDK1.7和1.8中的區(qū)別?
1.最重要的一點(diǎn)是底層結(jié)構(gòu)不一樣,1.7是數(shù)組+鏈表,1.8則是數(shù)組+鏈表+紅黑樹(shù)結(jié)構(gòu);
2.jdk1.7中當(dāng)哈希表為空時(shí),會(huì)先調(diào)用inflateTable()初始化一個(gè)數(shù)組;而1.8則是直接調(diào)用resize()擴(kuò)容;
3.插入鍵值對(duì)的put方法的區(qū)別,1.8中會(huì)將節(jié)點(diǎn)插入到鏈表尾部,而1.7中是采用頭插;
4.jdk1.7中的hash函數(shù)對(duì)哈希值的計(jì)算直接使用key的hashCode值,而1.8中則是采用key的hashCode異或上key的hashCode進(jìn)行無(wú)符號(hào)右移16位的結(jié)果,避免了只靠低位數(shù)據(jù)來(lái)計(jì)算哈希時(shí)導(dǎo)致的沖突,計(jì)算結(jié)果由高低位結(jié)合決定,使元素分布更均勻;
5.擴(kuò)容時(shí)1.8會(huì)保持原鏈表的順序,而1.7會(huì)顛倒鏈表的順序;而且1.8是在元素插入后檢測(cè)是否需要擴(kuò)容,1.7則是在元素插入前;
6.jdk1.8是擴(kuò)容時(shí)通過(guò)hash&cap==0將鏈表分散,無(wú)需改變hash值,而1.7是通過(guò)更新hashSeed來(lái)修改hash值達(dá)到分散的目的;
7.擴(kuò)容策略:1.7中是只要不小于閾值就直接擴(kuò)容2倍;而1.8的擴(kuò)容策略會(huì)更優(yōu)化,當(dāng)數(shù)組容量未達(dá)到64時(shí),以2倍進(jìn)行擴(kuò)容,超過(guò)64之后若桶中元素個(gè)數(shù)不小于7就將鏈表轉(zhuǎn)換為紅黑樹(shù),但如果紅黑樹(shù)中的元素個(gè)數(shù)小于6就會(huì)還原為鏈表,當(dāng)紅黑樹(shù)中元素不小于32的時(shí)候才會(huì)再次擴(kuò)容。
總結(jié)
本篇文章就到這里了,希望能對(duì)幫助到你,也希望你能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
MyBatis啟動(dòng)時(shí)控制臺(tái)無(wú)限輸出日志的原因及解決辦法
這篇文章主要介紹了MyBatis啟動(dòng)時(shí)控制臺(tái)無(wú)限輸出日志的原因及解決辦法的相關(guān)資料,需要的朋友可以參考下2016-07-07聊聊SpringBoot使用Nacos進(jìn)行服務(wù)注冊(cè)發(fā)現(xiàn)與配置管理問(wèn)題
Nacos支持基于DNS和基于RPC的服務(wù)發(fā)現(xiàn)(可以作為springcloud的注冊(cè)中心)、動(dòng)態(tài)配置服務(wù)(可以做配置中心)、動(dòng)態(tài)?DNS?服務(wù)。本文重點(diǎn)給大家介紹SpringBoot使用Nacos進(jìn)行服務(wù)注冊(cè)發(fā)現(xiàn)與配置管理,感興趣的朋友一起看看吧2022-01-01java中實(shí)現(xiàn)兼容ie6 7 8 9的spring4+websocket
這篇文章主要介紹了java中實(shí)現(xiàn)兼容ie6 7 8 9的spring4+websocket程序代碼,十分的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。2015-06-06AsyncHttpClient exception異常源碼流程解析
這篇文章主要為大家介紹了AsyncHttpClient的exception源碼流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12Java編譯錯(cuò)誤問(wèn)題:需要class,interface或enum
這篇文章主要介紹了Java編譯錯(cuò)誤問(wèn)題:需要class,interface或enum,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02SpringBoot 項(xiàng)目添加 MDC 日志鏈路追蹤的執(zhí)行流程
日志鏈路追蹤就是將一個(gè)標(biāo)志跨線程進(jìn)行傳遞,在一般的小項(xiàng)目中也就是在你新起一個(gè)線程的時(shí)候,或者使用線程池執(zhí)行任務(wù)的時(shí)候會(huì)用到,比如追蹤一個(gè)用戶請(qǐng)求的完整執(zhí)行流程,本文給大家介紹SpringBoot MDC 日志鏈路追蹤的代碼,感興趣的朋友一起看看吧2021-06-06Java學(xué)習(xí)關(guān)于循環(huán)和數(shù)組練習(xí)題整理
在本篇文章里小編給各位整理了關(guān)于Java學(xué)習(xí)關(guān)于循環(huán)和數(shù)組練習(xí)題相關(guān)內(nèi)容,有興趣的朋友們跟著參考學(xué)習(xí)下。2019-07-07Java Arrays.AsList原理及用法實(shí)例
這篇文章主要介紹了Java Arrays.AsList原理及用法實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11