最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java面試題沖刺第一天--基礎(chǔ)篇1

 更新時(shí)間:2021年07月13日 09:38:21   作者:_陳哈哈  
這篇文章主要為大家分享了最有價(jià)值的三道java面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下

面試題1:Java 中操作字符串都有哪些類?它們之間有什么區(qū)別? 正經(jīng)回答:

操作字符串的類有:StringStringBuffer、StringBuilder

String 和 StringBuffer、StringBuilder 的區(qū)別在于 String 聲明的是不可變的對(duì)象,每次操作都會(huì)生成新的 String 對(duì)象,然后將指針指向新的 String 對(duì)象,而 StringBuffer、StringBuilder 可以在原有對(duì)象的基礎(chǔ)上進(jìn)行操作,所以在經(jīng)常改變字符串內(nèi)容的情況下最好不要使用 String。

而StringBuffer 和 StringBuilder 最大的區(qū)別在于,StringBuffer 是線程安全的,而 StringBuilder 是非線程安全的,但 StringBuilder 的性能卻高于 StringBuffer,所以在單線程環(huán)境下推薦使用 StringBuilder,多線程環(huán)境下推薦使用 StringBuffer。

String StringBuffer StringBuilder
類是否可變 不可變(Final) 可變 可變
功能介紹 每次對(duì)String的操作都會(huì)在“常量池”中生成新的String對(duì)象 任何對(duì)它指向的字符串的操作都不會(huì)產(chǎn)生新的對(duì)象。每個(gè)StringBuffer對(duì)象都有一定的緩沖區(qū)容量,字符串大小沒有超過容量時(shí),不會(huì)分配新的容量,當(dāng)字符串大小超過容量時(shí),自動(dòng)擴(kuò)容 功能與StringBuffer相同,相比少了同步鎖,執(zhí)行速度更快
線程安全性 線程安全 線程安全 線程不安全
使用場(chǎng)景推薦 單次操作或循環(huán)外操作字符串 多線程操作字符串 單線程操作字符串

深入追問:

追問1:這三者在效率上怎么說?

StringBulider > StringBuffer > String

String <(StringBuffer,StringBuilder)的原因?

  • String:字符串常量
  • StringBuffer:字符串變量(有同步鎖)
  • StringBuilder:字符串變量(無同步鎖)

從上面的名字可以看到,String是"字符串常量",也就是不可改變的對(duì)象。源碼如下:

public final class String{}

對(duì)于上面這句話的理解你可能會(huì)產(chǎn)生這樣一個(gè)疑問 ,比如這段代碼:

String str = "唐伯虎";
str = str + "點(diǎn)香煙";
System.out.print(str); // result : "唐伯虎點(diǎn)香煙"

我們明明改變了String型的變量str啊,為什么說是沒有改變呢?我們來看一下這張對(duì)String操作時(shí)內(nèi)存變化的圖:

在這里插入圖片描述

我們可以看到,初始String值為"唐伯虎",然后在這個(gè)字符串后面加上新的字符串"點(diǎn)香煙",這個(gè)過程是需要重新在棧堆內(nèi)存中開辟內(nèi)存空間的,最終得到了"唐伯虎點(diǎn)香煙"字符串也相應(yīng)的需要開辟內(nèi)存空間,這樣短短的兩個(gè)字符串,卻需要開辟三次內(nèi)存空間,不得不說這是對(duì)內(nèi)存空間的極大浪費(fèi),執(zhí)行效率同理。

為了應(yīng)對(duì)經(jīng)常性操作字符串的場(chǎng)景,Java才提供了其他兩個(gè)操作字符串的類 —— StringBuffer、StringBuilder。

他們倆均屬于字符串變量,是可改變的對(duì)象,每當(dāng)我們用它們對(duì)字符串做操作時(shí),實(shí)際上是在一個(gè)對(duì)象上操作的,這樣就不會(huì)像String一樣創(chuàng)建一些而外的對(duì)象進(jìn)行操作了,速度自然就相對(duì)快了。

我們一般在StringBuffer、StringBuild類上的主要操作是 append 和 insert 方法,這些方法允許被重載,以接受任意類型的數(shù)據(jù)。每個(gè)方法都能有效地將給定的數(shù)據(jù)轉(zhuǎn)換成字符串,然后將該字符串的字符追加或插入到字符串緩沖區(qū)中。append 方法始終將這些字符添加到緩沖區(qū)的末端;而 insert 方法則在指定的點(diǎn)(index)添加字符。

  1. StringBuilder一個(gè)可變的字符序列是JDK1.5新增的。此類提供一個(gè)與 StringBuffer 兼容的 API,但不保證同步。該類被設(shè)計(jì)用作 StringBuffer 的一個(gè)簡(jiǎn)易替換,用在字符串緩沖區(qū)被單個(gè)線程使用的時(shí)候(這種情況很普遍)。如果可能,建議優(yōu)先采用S
  2. tringBuilder類,因?yàn)樵诖蠖鄶?shù)實(shí)現(xiàn)中,它比 StringBuffer 要快。且兩者的方法基本相同。然而在應(yīng)用程序要求線程安全的情況下,則必須使用 StringBuffer 類。

String 類型和 StringBuffer、 StringBuild類型的主要性能區(qū)別其實(shí)在于 String 是不可變的對(duì)象(final), 因此在每次對(duì) String 類型進(jìn)行改變的時(shí)候其實(shí)都等同于在堆中生成了一個(gè)新的 String 對(duì)象,然后將指針指向新的 String 對(duì)象,這樣不僅效率低下,而且大量浪費(fèi)有限的內(nèi)存空間,所以經(jīng)常改變內(nèi)容的字符串最好不要用 String 。因?yàn)槊看紊蓪?duì)象都會(huì)對(duì)系統(tǒng)性能產(chǎn)生影響,特別是當(dāng)內(nèi)存中的無引用對(duì)象過多了以后, JVM 的 GC 開始工作,那速度是一定會(huì)相當(dāng)慢的。另外當(dāng)GC清理速度跟不上new String的速度時(shí),還會(huì)導(dǎo)致內(nèi)存溢出Error,會(huì)直接kill掉主程序!報(bào)錯(cuò)如下:

Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded

Exception in thread "I/O dispatcher 3797236" java.lang.OutOfMemoryError: GC overhead limit exceeded

追問2:那StringBuffer和StringBuffer線程安全主要差在哪里呢?

StringBuffer和StringBuilder可以算是雙胞胎了,這兩者的方法沒有很大區(qū)別。但在線程安全性方面,StringBuffer允許多線程進(jìn)行字符操作。這是因?yàn)樵谠创a中StringBuffer的很多方法都被關(guān)鍵字synchronized 修飾了,而StringBuilder沒有。

synchronized的含義:   

每一個(gè)類對(duì)象都對(duì)應(yīng)一把鎖,當(dāng)某個(gè)線程A調(diào)用類對(duì)象O中的synchronized方法M時(shí),必須獲得對(duì)象O的鎖才能夠執(zhí)行M方法,否則線程A阻塞。一旦線程A開始執(zhí)行M方法,將獨(dú)占對(duì)象O的鎖。使得其它需要調(diào)用O對(duì)象的M方法的線程阻塞。只有線程A執(zhí)行完畢,釋放鎖后。那些阻塞線程才有機(jī)會(huì)重新調(diào)用M方法。這就是解決線程同步問題的鎖機(jī)制。 >  了解了synchronized的含義以后,大家可能都會(huì)有這個(gè)感覺。多線程編程中StringBuffer比StringBuilder要安全多了 ,事實(shí)確實(shí)如此。如果有多個(gè)線程需要對(duì)同一個(gè)字符串緩沖區(qū)進(jìn)行操作的時(shí)候,StringBuffer應(yīng)該是不二選擇。

注意:是不是String也不安全呢?事實(shí)上不存在這個(gè)問題,String是不可變的。線程對(duì)于堆中指定的一個(gè)String對(duì)象只能讀取,無法修改。試問:還有什么不安全的呢?

實(shí)際應(yīng)用場(chǎng)景中:

  • 如果不是在循環(huán)體中進(jìn)行字符串拼接的話,直接使用 String 的 “+” 就好了;
  • 單線程循環(huán)中操作大量字符串?dāng)?shù)據(jù) → StringBuilder.append();
  • 多線程循環(huán)中操作大量字符串?dāng)?shù)據(jù) → StringBuffer.append();

面試題2:請(qǐng)你說一下Error 和 Exception 區(qū)別是什么?

正經(jīng)回答:

Error 和 Exception 都是 Throwable 的子類,在Java中只有Throwable類型的實(shí)例才可以被拋出或者捕獲,它是異常處理機(jī)制的基本類型。

在這里插入圖片描述

  • Exception和Error體現(xiàn)了java平臺(tái)設(shè)計(jì)者對(duì)不同異常情況的分類,Exception是程序正常運(yùn)行中,可以預(yù)料的意外情況,可能并且應(yīng)該被捕獲,進(jìn)行相應(yīng)的處理。
  • Error是指正常情況下,不大可能出現(xiàn)的情況,絕大部分的Error都會(huì)導(dǎo)致程序處于非正常的、不可恢復(fù)的狀態(tài)。既然是非正常情況,不便于也不需要捕獲。常見的比如OutOfMemoryError之類都是Error的子類。
  • Exception又分為可檢查(checked)異常和不可檢查(unchecked)異常。可檢查異常在源代碼里必須顯式的進(jìn)行捕獲處理,這是編譯期檢查的一部分。不可檢查時(shí)異常是指運(yùn)行時(shí)異常,像NullPointerException、ArrayIndexOutOfBoundsException之類,通常是可以編碼避免的邏輯錯(cuò)誤,具體根據(jù)需要來判斷是否需要捕獲,并不會(huì)在編譯期強(qiáng)制要求。

面試題3:== 和 equals 的區(qū)別是什么

正經(jīng)回答:

  • == : 它的作用是判斷兩個(gè)對(duì)象的地址是不是相等。即,判斷兩個(gè)對(duì)象是不是同一個(gè)對(duì)象。(基本數(shù)據(jù)類型 == 比較的是值,引用數(shù)據(jù)類型 == 比較的是內(nèi)存地址)
  • equals(): 它的作用也是判斷兩個(gè)對(duì)象是否相等。但它一般有兩種使用情況:

情況1:類沒有覆蓋 equals() 方法。則通過 equals() 比較該類的兩個(gè)對(duì)象時(shí),等價(jià)于調(diào)用了Object類的equals() 方法,也就是通過“==”比較這兩個(gè)對(duì)象。

// Object類中的equals() 方法
public boolean equals(Object obj) {
    return (this == obj);
}

情況2:類覆蓋了 equals() 方法。一般,我們都會(huì)覆蓋 equals() 方法來兩個(gè)對(duì)象的內(nèi)容相等;若它們的內(nèi)容相等,則返回 true (即,認(rèn)為這兩個(gè)對(duì)象相等)。

// String類中的equals() 方法,已覆蓋,用于比較內(nèi)容
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;
}

深入追問:

追問1:如果我們不重寫equals() 方法,會(huì)怎么樣?

舉例說明:

重點(diǎn)說明:是否重寫Object類中的equals方法,會(huì)對(duì)結(jié)果造成的影響

public static void main(String[] args) {
    // 字符串比較
    String a = "陳哈哈";
    String b = "陳哈哈";
    if (a == b) {// true  a==b
        System.out.println("a==b");
    }
    if (a.equals(b)) {// true  a.equals(b)
        System.out.println("a.equals(b)");
    }
    // StringBuffer 對(duì)象比較,由于StringBuffer沒有重寫Object的equal方法,因此結(jié)果出現(xiàn)錯(cuò)誤
    StringBuffer c = new StringBuffer("陳哈哈");
    StringBuffer d = new StringBuffer("陳哈哈");
    if (c == d) {// false  c != d
        System.out.println("c == d");
    } else {
        System.out.println("c != d");
    }
    if (c.equals(d)) { // false 調(diào)用了Object類的equal方法
        System.out.println("StringBuffer equal true");
    }else {
        System.out.println("StringBuffer equal false");
    }
}
  • object的equals方法是比較的對(duì)象的內(nèi)存地址,而String的equals方法比較的是對(duì)象的值。
  • 因?yàn)镾tring中的equals方法是被重寫過的,而StringBuilder沒有重寫equals方法,從而調(diào)用的是Object類的equals方法,也就相當(dāng)于用了 ==;

追問2:重寫equals的同時(shí),我們需要重寫hashCode()方法么?為什么?

在重寫equals()方法時(shí),也有必要對(duì)hashCode()方法進(jìn)行重寫,尤其是當(dāng)我們自定義一個(gè)類,想把該類的實(shí)例存儲(chǔ)在集合中時(shí)。  

hashCode方法的常規(guī)約定為:值相同的對(duì)象必須有相同的hashCode,也就是equals()結(jié)果為相同,那么hashcode也要相同,equals()結(jié)果為不相同,那么hashcode也不相同;

當(dāng)我們使用equals方法比較說明對(duì)象相同,但hashCode不同時(shí),就會(huì)出現(xiàn)兩個(gè)hashcode值,比如在HashMap中,就會(huì)認(rèn)為這是兩個(gè)對(duì)象,因此會(huì)出現(xiàn)矛盾,說明equals方法和hashCode方法應(yīng)該成對(duì)出現(xiàn),當(dāng)我們對(duì)equals方法進(jìn)行重寫時(shí),也要對(duì)hashCode方法進(jìn)行重寫。

可以通過ide快捷鍵快速生成兩個(gè)方法,假設(shè)現(xiàn)在有一個(gè)學(xué)生Student類,其中有 age 和 name 兩個(gè)特征。生成代碼如下:

@Override
public boolean equals(Object o){
//首先比較兩個(gè)的地址值是否相同,如果相同,那內(nèi)容也一定相同
	if(this == o) return true;
//如果o為空值或者兩個(gè)對(duì)象的類型是否相同,如果類型不同或者o為空值則內(nèi)容一定不同
	if(o == null || getClass() != o.getClass()) return false;
//將object類型的實(shí)例強(qiáng)轉(zhuǎn)為Student類型
  	Student student = (Student)o;
//比較兩個(gè)實(shí)例的age是否相同
	if(age != student.age) return false;
//在比較name是否相同
	return name != null ? name.equals(student.name ) : student.name == null;
}
@Override
public int hashCode() {
	int result = age;
	result = 31 * result + (name != null ? name.hashCode() : 0);
	return result;
}

總結(jié)

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • SpringBoot項(xiàng)目中連接SQL Server的三種方式

    SpringBoot項(xiàng)目中連接SQL Server的三種方式

    連接SQL Server是許多Spring Boot項(xiàng)目中常見的需求之一,本文主要介紹了SpringBoot項(xiàng)目中連接SQL Server的三種方式,具有一定的參考價(jià)值 ,感興趣的可以了解一下
    2023-09-09
  • Nacos注冊(cè)中心的幾種調(diào)用方式詳解

    Nacos注冊(cè)中心的幾種調(diào)用方式詳解

    Spring Cloud Alibaba Nacos 作為近幾年最熱門的注冊(cè)中心和配置中心,也被國內(nèi)無數(shù)公司所使用,本文就來看下 Nacos 作為注冊(cè)中心時(shí),調(diào)用它的接口有幾種方式
    2023-10-10
  • Spring Bean生命周期之Bean的實(shí)例化詳解

    Spring Bean生命周期之Bean的實(shí)例化詳解

    這篇文章主要為大家詳細(xì)介紹了Spring Bean生命周期之Bean的實(shí)例化,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • java8如何用Stream查L(zhǎng)ist對(duì)象某屬性是否有重復(fù)

    java8如何用Stream查L(zhǎng)ist對(duì)象某屬性是否有重復(fù)

    這篇文章主要介紹了java8如何用Stream查L(zhǎng)ist對(duì)象某屬性是否有重復(fù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java字節(jié)流 從文件輸入輸出到文件過程解析

    Java字節(jié)流 從文件輸入輸出到文件過程解析

    這篇文章主要介紹了Java字節(jié)流 從文件輸入 輸出到文件過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • SpringBoot 鉤子接口的實(shí)現(xiàn)代碼

    SpringBoot 鉤子接口的實(shí)現(xiàn)代碼

    本文主要介紹了SpringBoot 鉤子接口,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • Mybatis內(nèi)置參數(shù)之_parameter和_databaseId的使用

    Mybatis內(nèi)置參數(shù)之_parameter和_databaseId的使用

    這篇文章主要介紹了Mybatis內(nèi)置參數(shù)之_parameter和_databaseId的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Spring Cache原理解析

    Spring Cache原理解析

    Spring Cache是一個(gè)框架,它提供了基于注解的緩存功能,使得開發(fā)者可以很方便地將緩存集成到他們的應(yīng)用程序中,這篇文章主要介紹了Spring Cache原理解析,需要的朋友可以參考下
    2024-05-05
  • 基于java使用釘釘機(jī)器人向釘釘群推送消息

    基于java使用釘釘機(jī)器人向釘釘群推送消息

    這篇文章主要介紹了基于java使用釘釘機(jī)器人向釘釘群推送消息,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Java字段Stream排序常用方式

    Java字段Stream排序常用方式

    這篇文章主要給大家介紹了關(guān)于Java字段Stream排序常用方式的相關(guān)資料,我們?cè)谔幚頂?shù)據(jù)的時(shí)候經(jīng)常會(huì)需要進(jìn)行排序后再返回給前端調(diào)用,比如按照時(shí)間升序排序,前端展示數(shù)據(jù)就是按時(shí)間先后進(jìn)行排序,需要的朋友可以參考下
    2023-09-09

最新評(píng)論

桓仁| 庆城县| 德安县| 梁河县| 宁津县| 紫金县| 南部县| 垫江县| 溧阳市| 临安市| 特克斯县| 革吉县| 宁化县| 安泽县| 台南市| 德惠市| 花垣县| 武陟县| 新安县| 互助| 临沭县| 乌拉特前旗| 沙洋县| 乌海市| 广东省| 聂拉木县| 建瓯市| 惠州市| 双江| 闸北区| 怀安县| 巍山| 成武县| 内丘县| 新昌县| 右玉县| 喀喇沁旗| 武陟县| 海阳市| 莱芜市| 开原市|