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

泛談Java中的不可變數(shù)據(jù)結(jié)構(gòu)

 更新時間:2019年05月23日 15:45:07   作者:銀河1號  
開發(fā)人員通常認(rèn)為擁有final引用,或者val在Kotlin或Scala中,足以使對象不可變。這篇博客文章深入研究了不可變引用和不可變數(shù)據(jù)結(jié)構(gòu),下面小編來和大家一起學(xué)習(xí)它

作為我最近一直在進(jìn)行的一些編碼訪談的一部分,有時會出現(xiàn)不變性問題。我自己并不過分教條,但每當(dāng)不需要可變狀態(tài)時,我會試圖擺脫導(dǎo)致可變性的代碼,這在數(shù)據(jù)結(jié)構(gòu)中通常是最明顯的。然而,似乎對不可變性的概念存在一些誤解,開發(fā)人員通常認(rèn)為擁有final引用,或者val在Kotlin或Scala中,足以使對象不可變。這篇博客文章深入研究了不可變引用和不可變數(shù)據(jù)結(jié)構(gòu)。

不可變數(shù)據(jù)結(jié)構(gòu)的好處

不可變數(shù)據(jù)結(jié)構(gòu)具有顯著優(yōu)勢,例如:

  • 沒有無效的狀態(tài)
  • 線程安全
  • 易于理解的代碼
  • 更容易測試代碼
  • 可用于值類型

沒有無效的狀態(tài)

當(dāng)一個對象是不可變的時,很難讓對象處于無效狀態(tài)。該對象只能通過其構(gòu)造函數(shù)實例化,這將強制對象的有效性。這樣,可以強制執(zhí)行有效狀態(tài)所需的參數(shù)。一個例子:

Address address = new Address();
address.setCity("Sydney");
// address is in invalid state now, since the country hasn't been set.
Address address = new Address("Sydney", "Australia");
// Address is valid and doesn't have setters, so the address object is always valid.

線程安全

由于無法更改對象,因此可以在線程之間共享它,而不會出現(xiàn)競爭條件或數(shù)據(jù)突變問題。

易于理解的代碼

與無效狀態(tài)的代碼示例類似,使用構(gòu)造函數(shù)通常比初始化方法更容易。這是因為構(gòu)造函數(shù)強制執(zhí)行必需的參數(shù),而setter或initializer方法在編譯時不會強制執(zhí)行。

更易于測試的代碼

由于對象更具可預(yù)測性,因此不必測試初始化方法的所有排列,即在調(diào)用類的構(gòu)造函數(shù)時,該對象有效或無效。使用這些類的代碼的其他部分變得更可預(yù)測,具有更少的NullPointerException機會。有時,當(dāng)傳遞對象時,有些方法可能會改變對象的狀態(tài)。例如:

public boolean isOverseas(Address address) {
 if(address.getCountry().equals("Australia") == false) {
  address.setOverseas(true); // address has now been mutated!
  return true;
 } else {
  return false;
 }
}

一般來說,上面的代碼是不好的做法。它返回一個布爾值,并可能改變對象的狀態(tài)。這使得代碼更難理解和測試。更好的解決方案是從Address 類中刪除setter ,并通過測試國家名稱返回一個布爾值。更好的方法是將此邏輯移動到 Address 類本身(address.isOverseas())。當(dāng)確實需要設(shè)置狀態(tài)時,在不改變輸入的情況下制作原始對象的副本。

可用于值類型

想象一下金額,比如10美元。10美元將永遠(yuǎn)是10美元。在代碼中,這可能看起來像 public Money(final BigInteger amount, final Currency currency)。正如您在此代碼中看到的那樣,不可能將10美元的值更改為除此之外的任何值,因此,上述內(nèi)容可以安全地用于值類型。

最終引用不要使對象不可變

如前所述,我經(jīng)常遇到的問題之一是這些開發(fā)人員中的很大一部分并不完全理解最終引用和不可變對象之間的區(qū)別。似乎這些開發(fā)人員的共同理解是,變量成為最終的那一刻,數(shù)據(jù)結(jié)構(gòu)變得不可變。不幸的是,這并不是那么簡單,我想一勞永逸地把這種誤解帶出世界:

A final reference does not make your objects immutable!

換句話說,下面的代碼并沒有使對象不變:

final Person person = new Person("John");

為什么不?好吧,雖然person是最后一個字段而且無法重新分配,但是 Person類可能有一個setter方法或其他mutator方法,可以執(zhí)行如下操作:

person.setName("Cindy");

無論最終修飾符如何,這都是一件非常容易的事情?;蛘撸?Person類可能會公開這樣的地址列表。訪問此列表允許您向其添加地址,因此,如下所示改變 person對象:

person.getAddresses().add(new Address("Sydney"));

好了,既然我們已經(jīng)解決了這個問題,那么讓我們深入了解一下我們?nèi)绾问诡惒豢勺?。在設(shè)計我們的類時,我們需要記住幾件事:

  • 不要以可變的方式暴露內(nèi)部狀態(tài)
  • 要在內(nèi)部改變狀態(tài)
  • 確保子類不會覆蓋上述行為

根據(jù)以下準(zhǔn)則,讓我們設(shè)計一個更好的Person class 版本 。

public final class Person {// final class, can't be overridden by subclasses
 private final String name;  // final for safe publication in multithreaded applications
 private final List<Address> addresses;
 public Person(String name, List<Address> addresses) {
  this.name = name;
  this.addresses = List.copyOf(addresses); // makes a copy of the list to protect from outside mutations (Java 10+).
    // Otherwise, use Collections.unmodifiableList(new ArrayList<>(addresses));
 }
 public String getName() {
  return this.name; // String is immutable, okay to expose
 }
 public List<Address> getAddresses() {
  return addresses; // Address list is immutable
 }
}
public final class Address { // final class, can't be overridden by subclasses
 private final String city; // only immutable classes
 private final String country;
 public Address(String city, String country) {
  this.city = city;
  this.country = country;
 }
 public String getCity() {
  return city;
 }
 public String getCountry() {
  return country;
 }
}

現(xiàn)在,可以使用以下代碼:

import java.util.List;
final Person person = new Person("John", List.of(new Address(“Sydney”, "Australia"));

現(xiàn)在,上面的代碼是不可變的,但是由于Person 和 Address 類的設(shè)計 ,同時還有最終引用,因此無法將person變量重新分配給其他任何東西。

更新:正如有些人提到的,上面的代碼仍然是可變的,因為我沒有在構(gòu)造函數(shù)中復(fù)制地址列表。因此,如果不在ArrayList() 構(gòu)造函數(shù)中調(diào)用new ,仍然可以執(zhí)行以下操作:

final List<Address> addresses = new ArrayList<>();
addresses.add(new Address("Sydney", "Australia"));
final Person person = new Person("John", addressList);
addresses.clear();

但是,由于在構(gòu)造函數(shù)中創(chuàng)建了一個新副本,上面的代碼將不再影響類中復(fù)制的地址列表引用Person ,從而使代碼安全。

我希望上述內(nèi)容有助于理解最終和不變性之間的差異。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 走進(jìn)JDK之不可變類String

    走進(jìn)JDK之不可變類String

    這篇文章主要給大家介紹了JDK之不可變類String的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用JDK具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • SpringAop源碼及調(diào)用過程概述

    SpringAop源碼及調(diào)用過程概述

    這篇文章主要介紹了SpringAop源碼及調(diào)用過程概述,Spring AOP(面向切面編程)是Spring框架的一個重要特性,它提供了一種在程序運行期間動態(tài)地將額外的行為織入到代碼中的方式,需要的朋友可以參考下
    2023-10-10
  • MyBatis學(xué)習(xí)教程(六)-調(diào)用存儲過程

    MyBatis學(xué)習(xí)教程(六)-調(diào)用存儲過程

    這篇文章主要介紹了MyBatis學(xué)習(xí)教程(六)-調(diào)用存儲過程的相關(guān)資料,非常不錯,具有參考借鑒價值,感興趣的朋友一起看下吧
    2016-05-05
  • java根據(jù)負(fù)載自動抓取jstack?dump詳情

    java根據(jù)負(fù)載自動抓取jstack?dump詳情

    這篇文章主要介紹了java根據(jù)負(fù)載自動抓取jstack?dump詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • HttpServletRequest對象簡介_動力節(jié)點Java學(xué)院整理

    HttpServletRequest對象簡介_動力節(jié)點Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了HttpServletRequest對象簡介的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Intellij IDEA 2017.3使用Lombok及常用注解介紹

    Intellij IDEA 2017.3使用Lombok及常用注解介紹

    這篇文章主要介紹了Intellij IDEA 2017.3使用Lombok及常用注解介紹,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Java實現(xiàn)單鏈表SingleLinkedList增刪改查及反轉(zhuǎn) 逆序等

    Java實現(xiàn)單鏈表SingleLinkedList增刪改查及反轉(zhuǎn) 逆序等

    單鏈表是鏈表的其中一種基本結(jié)構(gòu)。一個最簡單的結(jié)點結(jié)構(gòu)如圖所示,它是構(gòu)成單鏈表的基本結(jié)點結(jié)構(gòu)。在結(jié)點中數(shù)據(jù)域用來存儲數(shù)據(jù)元素,指針域用于指向下一個具有相同結(jié)構(gòu)的結(jié)點。 因為只有一個指針結(jié)點,稱為單鏈表
    2021-10-10
  • java版數(shù)獨游戲界面實現(xiàn)(二)

    java版數(shù)獨游戲界面實現(xiàn)(二)

    這篇文章主要為大家詳細(xì)介紹了java版數(shù)獨游戲界面實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • idea perttier的使用和縮進(jìn)改為4不成功問題及解決

    idea perttier的使用和縮進(jìn)改為4不成功問題及解決

    這篇文章主要介紹了idea perttier的使用和縮進(jìn)改為4不成功問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • java 中RandomAccess接口源碼分析

    java 中RandomAccess接口源碼分析

    這篇文章主要介紹了java 中RandomAccess接口源碼分析的相關(guān)資料,需要的朋友可以參考下
    2017-05-05

最新評論

界首市| 平江县| 吴桥县| 英山县| 庄浪县| 北碚区| 肇庆市| 天长市| 甘孜县| 彝良县| 齐齐哈尔市| 巍山| 资溪县| 稷山县| 九江市| 七台河市| 临漳县| 八宿县| 区。| 徐闻县| 潼南县| 涪陵区| 屏东市| 宜城市| 馆陶县| 海安县| 铅山县| 五河县| 嘉鱼县| 平和县| 图木舒克市| 吉林省| 新乡市| 仁寿县| 黔江区| 庆安县| 清水县| 图片| 兰考县| 寿宁县| 都江堰市|