JAVA 知識

  • ==equalshashcode的區(qū)別

    1. ==
    a. 基本類型:比較的是值是否相等
    b. 引用類型(類、接口、數(shù)組):比較的是內(nèi)存存放地址是否相同
    

    補(bǔ)充:對象存放在堆中,棧中存放的是對象的引用地址。由此可見"=="是對棧中的值進(jìn)行比較,如果要比較堆中對象的內(nèi)容是否相同,則需要重寫equals。

    2. equals
    a. 默認(rèn)情況:判斷對象的內(nèi)存地址引用是否相同,即判斷是否為同一對象。
    b. 重寫對象equals方法:視方法實(shí)現(xiàn)而定。
    
    3. hashCode

    通過哈希算法(散列算法)計算返回一個hash碼數(shù)值,用于對對象進(jìn)行散列的時候作為key輸入,為保證散列的存取性能,因此hash會盡可能不同。

    作用:Java中集合有兩類:List、Set。前者集合內(nèi)元素是有序、可重復(fù)的;后者元素?zé)o序、不可重復(fù)。為保證元素不重復(fù),采用哈希表的原理來計算判斷。

    當(dāng)集合要添加新的元素時,先調(diào)用這個元素的hashCode方法,定位到它應(yīng)該防止的物理位置上。該位置無元素時,則直接存儲;該位置上已有元素,則需通過equals方法對比,為保證集合內(nèi)元素唯一,所以比較相同則不存儲。從而大大降低存儲效率。

  • StringStringBuffer、StringBuilder的區(qū)別

    Java語言中,有4個類對字符或者字符串進(jìn)行操作(Character、String、StringBufferStringBuider、StringTokenizer),其中Character用于單個字符操作,String用于字符串操作,屬于不可變類;而StringBuffer也是用于字符串操作,但屬于可變類。

    String是不可變類,也就是說String一旦被創(chuàng)建,其值將不能被改變,因此適合在需要被共享的場合中使用,如果用String來保存一個經(jīng)常被修改的字符串,在字符串被修改是會比StringBuffer多很多附加操作,同時生成很多無用對象,從而會影響程序性能。當(dāng)一個字符串經(jīng)常需要被修改時,最好使用StringBuffer來實(shí)現(xiàn)。

    StringBuilder是可變類,與StringBuffer類似,都是字符串緩沖區(qū),但StringBuilder是不是線程安全的,如果只是單線程中使用字符串緩沖區(qū),那StringBuilder效率更高些。當(dāng)有多個線程訪問時,最好使用線程安全的StringBuffer。因?yàn)?code>StringBuffer必要時可以對這些方法進(jìn)行同步,所以任意特定實(shí)例上的所有操作就好像是以串行順序發(fā)生的,改順序與所涉及的每個線程進(jìn)行的方法調(diào)用順序一致。
    執(zhí)行效率:StringBuilder > StringBuffer > String

  • 數(shù)組與鏈表的區(qū)別

    1. 數(shù)組的特點(diǎn)
    1. 內(nèi)存中為一塊連續(xù)的區(qū)域
    2. 需預(yù)留空間,使用前要先申請所占內(nèi)存大小,因此可能會浪費(fèi)存儲空間
    3. 插入數(shù)據(jù)和刪除數(shù)據(jù)效率低。刪除插入時都需大規(guī)模元素移動
    4. 隨機(jī)讀取效率很高。因?yàn)閿?shù)組是連續(xù)的,知道每一個數(shù)據(jù)的內(nèi)存地址,可以直接找到該地址的數(shù)據(jù)
    5. 不利于擴(kuò)展,數(shù)組定義的空間不夠時需重新定義數(shù)組
    
    2. 鏈表的特點(diǎn)
    1. 可以存在內(nèi)存中任何地方,不要求連續(xù)
    2. 每個數(shù)據(jù)都保存了下一個數(shù)據(jù)的內(nèi)存地址,可以通過這個地址找到下一個數(shù)據(jù)
    3. 增加刪除數(shù)據(jù)很容易
    4. 查找數(shù)據(jù)時效率低。因?yàn)椴痪哂须S機(jī)訪問性,所以訪問某個位置的數(shù)據(jù)都要從第一個數(shù)據(jù)開始訪問,然后根據(jù)第一個數(shù)據(jù)保存的下一個數(shù)據(jù)地址找到第二個數(shù)據(jù),必須從第一個人開始問起
    5. 不指定大小,擴(kuò)展方便
    
  • List、Map、Set的區(qū)別

    ListSet是存儲單列數(shù)據(jù)的集合,Map是存儲鍵值對這樣的雙列數(shù)據(jù)的集合。
    List中數(shù)據(jù)有序、可重復(fù)。
    Map中數(shù)據(jù)無序、鍵不可重復(fù)但值可重復(fù)。
    Set中數(shù)據(jù)無序、不可重復(fù),元素在集合中的位置由元素的hashCode決定。

    List接口實(shí)現(xiàn)類:

    1. LinkedList:基于鏈表實(shí)現(xiàn),內(nèi)存散列,增刪快,查找慢。
    2. ArrayList:基于數(shù)組實(shí)現(xiàn),非線程安全,效率高,增刪慢,查找快。
    3. Vector:基于數(shù)組實(shí)現(xiàn),線程安全,效率低,增刪慢,查找慢。
    

    Set接口實(shí)現(xiàn)類:

    1. HashSet:用HashMap實(shí)現(xiàn),不可重復(fù),使用時需重寫equals和hashCode
    2. LinkedHashSet:繼承自HashSet,同時基于LinkedHashMap來進(jìn)行實(shí)現(xiàn)
    

    Map接口實(shí)現(xiàn)類:

    1. HashMap:基于哈希表的Map接口實(shí)現(xiàn),非線程安全,高效,支持null值和null鍵
    2. HashTable:線程安全,低效,不支持null值和null鍵
    3. LinkedHashMap:繼承自HashMap,保存了記錄的插入順序
    4. SortMap接口:TreeMap,能夠把保存的記錄根據(jù)鍵值對排序,默認(rèn)升序
    
  • WaitSleep區(qū)別

    Wait用于線程間通信,當(dāng)?shù)却龡l件為真且線程被喚醒時他會釋放鎖。
    Sleep釋放CPU資源或者讓當(dāng)前線程停止執(zhí)行一段時間,但不會釋放鎖。

  • SerializableParcelable

    將某個特定的對象保存到文件中,隔一段時間后再把它讀取到內(nèi)存中使用,那么該對象就需要實(shí)現(xiàn)序列化操作,在java可以使用Serializable接口實(shí)現(xiàn)對象的序列化,而在android中既可以使用Serializable、Parcelable實(shí)現(xiàn)對象序列化。但是內(nèi)存操作是更傾向于實(shí)現(xiàn)Parcelable接口,這樣傳輸效率更高。

    序列化:
    由于存在于內(nèi)存中的對象都是暫時的,無法長期貯存,為了把對象的狀態(tài)保存下來,這是需要把對象寫入到磁盤或者其他介質(zhì)中
    反序列化:
    把已存在磁盤或者其他介質(zhì)中的對象,讀取到內(nèi)存中,以便后續(xù)操作
    序列化是指將對象實(shí)例的狀態(tài)存儲到存儲媒體的過程。在此過程中,先將對象的公共字段和私有字段以及類的名稱(包括類所在的程序集)轉(zhuǎn)換成字節(jié)流,然后把字節(jié)流寫入到數(shù)據(jù)流。在隨后對對象進(jìn)行反序列化時,將創(chuàng)建出與原對象完全相同的副本

    • Serializable
      該方式主要依靠ObjectInputStreamObjectOutputStream實(shí)現(xiàn)序列化與反序列化,通過流對象把類對象寫到文件中,并在需要時恢復(fù)對象。但是兩者并不是同一個對象,反序列化后的對象是新創(chuàng)建的。該方式使用了反射,序列化過程較慢,在序列化的時候會創(chuàng)建許多臨時對象,容易觸發(fā)垃圾回收

      注:
      1. 如果反序列類的成員變量的類型或者類名發(fā)生了變化,那么即使serialVersionUID相同也無法正常反序列化成功
      2. 靜態(tài)成員變量屬于類不屬于對象,不會參與序列化過程,使用transient關(guān)鍵字標(biāo)記的成員變量也不會參與序列化過程

    • Parcelable
      序列化過程,writeToParcel方法實(shí)現(xiàn)序列化功能,其內(nèi)部是通過Parcel的一系列write方法完成的,接著通過CREATOR內(nèi)部對象來完成反序列化,其內(nèi)部通過createFromParcel方法來創(chuàng)建序列化對象并通過newArray方法創(chuàng)建數(shù)組,最終利用Parcel的一系列read方法完成發(fā)序列化,最后由describeContents完成內(nèi)容描述功能,該方法一般返回0,僅當(dāng)對象中存在文件描述符時返回1。
      通過writeToParcel將我們的對象映射成Parcel對象,再通過createFromParcel將Parcel對象映射成我們的對象。這個過程需要自行實(shí)現(xiàn)且寫的順序和讀的順序必須一致。大致原理是將一個完整的對象進(jìn)行分解,而分解后的每一部分都是Intent所支持的數(shù)據(jù)類型,這樣就實(shí)現(xiàn)傳遞對象的功能了

    • ParcelableSerializable區(qū)別

      • 兩者實(shí)現(xiàn)差異
        Serializable的實(shí)現(xiàn),只需要實(shí)現(xiàn)該接口即可。這只是給對象打了個標(biāo)記(UID),系統(tǒng)會自動將其序列化。而Parcelable的實(shí)現(xiàn),不僅需要實(shí)現(xiàn)該接口,還需要再累中添加一個靜態(tài)成員變量CREATOR,這個變量需要實(shí)現(xiàn)Parcelable.Creator接口,并實(shí)現(xiàn)讀寫的抽象方法
      • 兩者設(shè)計初衷
        Serializable是為了序列化對象到本地文件、數(shù)據(jù)庫、網(wǎng)絡(luò)流、RMI以便數(shù)據(jù)傳輸,當(dāng)然這種傳輸可以是程序內(nèi)的也可以是程序間的。而Android的Parcelable是由于Serializable效率過低,消耗大,而android中數(shù)據(jù)傳遞主要是在內(nèi)存環(huán)境中,因此Parcelable的出現(xiàn)是為了滿足數(shù)據(jù)在內(nèi)存中低開銷而且高效傳遞問題
      • 兩者效率選擇
        Parcelable的性能比Serializable好,在內(nèi)存開銷方面較小,所以Android應(yīng)用程序在內(nèi)存間數(shù)據(jù)傳輸時推薦使用Parcelable,如activity間傳輸數(shù)據(jù)和AIDL數(shù)據(jù)傳遞,Serializable將數(shù)據(jù)持久化的操作方便,因此在將對象序列化到存儲設(shè)置中或?qū)ο笮蛄谢笸ㄟ^網(wǎng)絡(luò)傳輸時建議選擇Serializable(Parcelable也是可以的,只不過實(shí)現(xiàn)和操作過程太麻煩,并且為了防止Android版本不同而導(dǎo)致Parcelable可能不同,因此在序列化到存儲設(shè)備或者網(wǎng)絡(luò)傳輸方面還是盡量選擇Serializable接口)
      • 兩者注意點(diǎn)
        兩者執(zhí)行反序列操作后的對象都是新創(chuàng)建的,內(nèi)容一樣但對象不同
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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