2022年java面試整理,八股文篇-4年經(jīng)驗(yàn)

有些問(wèn)題真的挺無(wú)語(yǔ)的,面高級(jí)怎么還在問(wèn)這些

==和equals的區(qū)別, 0.1*5 == 0.5的結(jié)果

==對(duì)于基本類(lèi)型,比較的是值,但對(duì)于引用類(lèi)型,比較的是內(nèi)存地址
equals對(duì)于引用類(lèi)型,首先,equals會(huì)用==比較兩個(gè)類(lèi)型在內(nèi)存中的地址,如果一樣,則直接返回true,如果不一樣,則直接往下走,再判斷是否為string類(lèi)型,如果不是,則強(qiáng)轉(zhuǎn)為string類(lèi)型,再將字符串?dāng)?shù)組拆分為單個(gè)字符,一一比較,有一個(gè)不相同,則返回false,否則返回true
equals的源碼如下:

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

從上面可以看出 0.1*5 == 0.5 的結(jié)果應(yīng)該為true,因?yàn)樗麄兪腔緮?shù)據(jù)類(lèi)型,直接比較值


image.png

還遇到了另外一個(gè)問(wèn)題,如下圖。


image.png

因?yàn)镾tring a = "abc"在編譯的時(shí)候,jvm將abc放入常量池,并在常量池中創(chuàng)建該常量的地址,然后將a去指向這個(gè)常量,當(dāng)我們執(zhí)行String a = "abc"的時(shí)候,會(huì)去常量池中尋找有沒(méi)有abc這個(gè)常量,如果有,則將b指向它,沒(méi)有就創(chuàng)建,所以a和b都指向常量池中的abc,故內(nèi)存地址相同。
而在 String str1 = new String("abc")中,首先會(huì)在堆內(nèi)存中去開(kāi)辟一個(gè)空間去存儲(chǔ)abc,當(dāng)我們?cè)賜ew對(duì)象的時(shí)候,還會(huì)再去開(kāi)辟,所以二則的內(nèi)存地址不相同,故返回false

聚簇索引和非聚簇索引的區(qū)別

  • 聚集索引
    聚集索引即索引結(jié)構(gòu)和數(shù)據(jù)一起存放的索引。主鍵索引屬于聚集索引。
    在 MySQL 中,InnoDB 引擎的表的 .ibd文件就包含了該表的索引和數(shù)據(jù),對(duì)于 InnoDB 引擎表來(lái)說(shuō),該表的索引(B+樹(shù))的每個(gè)非葉子節(jié)點(diǎn)存儲(chǔ)索引,葉子節(jié)點(diǎn)存儲(chǔ)索引和索引對(duì)應(yīng)的數(shù)據(jù)。
    聚集索引的優(yōu)點(diǎn):聚集索引的查詢速度非常的快,因?yàn)檎麄€(gè) B+樹(shù)本身就是一顆多叉平衡樹(shù),葉子節(jié)點(diǎn)也都是有序的,定位到索引的節(jié)點(diǎn),就相當(dāng)于定位到了數(shù)據(jù)。
    聚集索引的缺點(diǎn)
    1. 依賴(lài)于有序的數(shù)據(jù) :因?yàn)?B+樹(shù)是多路平衡樹(shù),如果索引的數(shù)據(jù)不是有序的,那么就需要在插入時(shí)排序,如果數(shù)據(jù)是整型還好,否則類(lèi)似于字符串或 UUID 這種又長(zhǎng)又難比較的數(shù)據(jù),插入或查找的速度肯定比較慢。
    2. 更新代價(jià)大:如果對(duì)索引列的數(shù)據(jù)被修改時(shí),那么對(duì)應(yīng)的索引也將會(huì)被修改,而且聚集索引的葉子節(jié)點(diǎn)還存放著數(shù)據(jù),修改代價(jià)肯定是較大的,所以對(duì)于主鍵索引來(lái)說(shuō),主鍵一般都是不可被修改的。
  • 非聚集索引
    非聚集索引即索引結(jié)構(gòu)和數(shù)據(jù)分開(kāi)存放的索引。二級(jí)索引屬于非聚集索引。
    非聚集索引的葉子節(jié)點(diǎn)并不一定存放數(shù)據(jù)的指針,因?yàn)槎?jí)索引的葉子節(jié)點(diǎn)就存放的是主鍵,根據(jù)主鍵再回表查數(shù)據(jù)。
    非聚集索引的優(yōu)點(diǎn)
  1. 更新代價(jià)比聚集索引要小 。非聚集索引的更新代價(jià)就沒(méi)有聚集索引那么大了,非聚集索引的葉子節(jié)點(diǎn)是不存放數(shù)據(jù)的
    非聚集索引的缺點(diǎn)
  2. 同樣以來(lái)有序的數(shù)據(jù)
  3. 可能會(huì)二次查詢(回表):這應(yīng)該是非聚集索引最大的缺點(diǎn)了。 當(dāng)查到索引對(duì)應(yīng)的指針或主鍵后,可能還需要根據(jù)指針或主鍵再到數(shù)據(jù)文件或表中查詢。

這是mysql的文件截圖


image.png

聚集索引和非聚集索引:
image.png

因?yàn)槭菍?shí)戰(zhàn)面試,索引其他的問(wèn)題就不擴(kuò)展了

JVM內(nèi)存模型,垃圾清理算法

  • jdk1.8之前


    image.png
  • jdk1.8


    image.png

堆存放的是對(duì)象實(shí)例,幾乎所有的對(duì)象實(shí)例以及數(shù)組都在這里分配內(nèi)存。
比如現(xiàn)在我們有個(gè)User類(lèi),
現(xiàn)在 User user = new User();
在user對(duì)象初始化的時(shí)候默認(rèn)code和name為null。(根據(jù)不同的數(shù)據(jù)類(lèi)型來(lái),比如int就默認(rèn)為0)
user.setName = "小明";
這里就把name從null重新賦值了小明。
從這里可以看出對(duì)象創(chuàng)建過(guò)程是 new對(duì)象->設(shè)默認(rèn)值->調(diào)用構(gòu)造方式設(shè)初始值

image.png


@Data
@Accessors(chain = true)
public class User {

    private String code;
    private String name;

}

方法區(qū)(元空間)

方法區(qū)屬于是 JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)域的一塊邏輯區(qū)域,是各個(gè)線程共享的內(nèi)存區(qū)域。方法區(qū)存放類(lèi)信息、字段信息、方法信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼緩存等數(shù)據(jù)。

棧 (本地方法棧,虛擬機(jī)棧,程序計(jì)數(shù)器)

垃圾回收算法

  • 標(biāo)記-清除算法
    該算法分為“標(biāo)記”和“清除”階段:首先標(biāo)記出所有不需要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收掉所有沒(méi)有被標(biāo)記的對(duì)象。它是最基礎(chǔ)的收集算法,后續(xù)的算法都是對(duì)其不足進(jìn)行改進(jìn)得到。這種垃圾收集算法會(huì)帶來(lái)兩個(gè)明顯的問(wèn)題:

效率問(wèn)題
空間問(wèn)題(標(biāo)記清除后會(huì)產(chǎn)生大量不連續(xù)的碎片)

  • 標(biāo)記-復(fù)制算法
    為了解決效率問(wèn)題,“標(biāo)記-復(fù)制”收集算法出現(xiàn)了。它可以將內(nèi)存分為大小相同的兩塊,每次使用其中的一塊。當(dāng)這一塊的內(nèi)存使用完后,就將還存活的對(duì)象復(fù)制到另一塊去,然后再把使用的空間一次清理掉。這樣就使每次的內(nèi)存回收都是對(duì)內(nèi)存區(qū)間的一半進(jìn)行回收。
  • 標(biāo)記-整理算法
    根據(jù)老年代的特點(diǎn)提出的一種標(biāo)記算法,標(biāo)記過(guò)程仍然與“標(biāo)記-清除”算法一樣,但后續(xù)步驟不是直接對(duì)可回收對(duì)象回收,而是讓所有存活的對(duì)象向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存。
  • 分代收集算法
    當(dāng)前虛擬機(jī)的垃圾收集都采用分代收集算法,這種算法沒(méi)有什么新的思想,只是根據(jù)對(duì)象存活周期的不同將內(nèi)存分為幾塊。一般將 java 堆分為新生代和老年代,這樣我們就可以根據(jù)各個(gè)年代的特點(diǎn)選擇合適的垃圾收集算法。

參考:

  1. ==和equals
  2. 聚集索引與非聚集索引
  3. Java 內(nèi)存區(qū)域詳解
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容