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

詳解Java如何實現(xiàn)一個像String一樣不可變的類

 更新時間:2022年11月28日 09:36:27   作者:鴨血粉絲Tang  
說到?String?大家都知道?String?是一個不可變的類;雖然用的很多,那不知道小伙伴們有沒有想過怎么樣創(chuàng)建一個自己的不可變的類呢?這篇文章就帶大家來實踐一下,創(chuàng)建一個自己的不可變的類

如果問你在日常開發(fā)中用到的最多的一個 Java 類是什么,阿粉敢打賭絕對是 String.class。說到 String 大家都知道 String 是一個不可變的類;雖然用的很多,那不知道小伙伴們有沒有想過怎么樣創(chuàng)建一個自己的不可變的類呢?這篇文章阿粉就帶大家來實踐一下,創(chuàng)建一個自己的不可變的類。

特性

在手動編寫代碼之前,我們先了解一下不可變類都有哪些特性,

  • 定義類的時候需要使用 final 關(guān)鍵字進行修飾:之所以使用 final 進行修飾是因為這樣可以避免被其他類繼承,一旦有了子類繼承就會破壞父類的不可變性機制;
  • 成員變量需要使用 final 關(guān)鍵詞修飾,并且需要是 private 的:避免屬性被外部修改;
  • 成員變量不可提供 setter 方法,只能提供 getter 方法:避免被外部修改,并且避免返回成員變量本身;
  • 提供所有字段的構(gòu)造函數(shù);

實操

知道了不可變類的一些基本特性之后,我們來實際寫代碼操作一下,以及我們會驗證一下,如果不按照上面的要求來編寫的話,會出現(xiàn)什么樣的問題。

這里我們定義一個 Teacher 類來測試一下,按照我們上面提到的幾點,我們給類和屬性的定義都加上 final 代碼如下所示。

package?com.example.demo.immutable;

import?java.util.List;
import?java.util.Map;

public?final?class?Teacher?{
??private?final?String?name;
??private?final?List<String>?students;
??private?final?Address?address;
??private?final?Map<String,?String>?metadata;

??public?Teacher(String?name,?List<String>?students,?Address?address,?Map<String,?String>?metadata)?{
????this.name?=?name;
????this.students?=?students;
????this.address?=?address;
????this.metadata?=?metadata;
??}

??public?String?getName()?{
????return?name;
??}


??public?List<String>?getStudents()?{
????return?students;
??}

??public?Address?getAddress()?{
????return?address;
??}

??public?Map<String,?String>?getMetadata()?{
????return?metadata;
??}
}
package?com.example.demo.immutable;

public?class?Address?{
??private?String?country;
??private?String?city;

??public?String?getCountry()?{
????return?country;
??}

??public?void?setCountry(String?country)?{
????this.country?=?country;
??}

??public?String?getCity()?{
????return?city;
??}

??public?void?setCity(String?city)?{
????this.city?=?city;
??}
}

我們思考一下,上面的代碼是否真正的做到了不可變,好,我們思考三秒鐘,心里默默的數(shù)三下。為了回答這個問題,我們看下下面的測試代碼。

package?com.example.demo;

import?com.example.demo.immutable.Address;
import?com.example.demo.immutable.Teacher;

import?java.util.ArrayList;
import?java.util.HashMap;
import?java.util.List;
import?java.util.Map;

/**
?*?<br>
?*?<b>Function:</b><br>
?*?<b>Author:</b>@author?Silence<br>
?*?<b>Date:</b>2022-11-22 21:17<br>
?*?<b>Desc:</b>無<br>
?*/
public?class?ImmutableDemo?{

??public?static?void?main(String[]?args)?{
????List<String>?students?=?new?ArrayList<>();
????students.add("鴨血粉絲?1");
????students.add("鴨血粉絲?2");
????students.add("鴨血粉絲?3");
????Address?address?=?new?Address();
????address.setCountry("中國");
????address.setCity("深圳");
????Map<String,?String>?metadata?=?new?HashMap<>();
????metadata.put("hobby",?"籃球");
????metadata.put("age",?"29");
????Teacher?teacher?=?new?Teacher("Java極客技術(shù)",?students,?address,?metadata);
????System.out.println(teacher.getStudents().size());
????System.out.println(teacher.getMetadata().size());
????System.out.println(teacher.getAddress().getCity());

????//?修改屬性
????teacher.getStudents().add("小明");
????teacher.getMetadata().put("weight",?"120");
????teacher.getAddress().setCity("廣州");

????System.out.println(teacher.getStudents().size());
????System.out.println(teacher.getMetadata().size());
????System.out.println(teacher.getAddress().getCity());
??}

}

運行的結(jié)果如下截圖所示,通過測試我們可以發(fā)現(xiàn),簡單的只添加 final 關(guān)鍵字是不能解決不可變性的,我們當前的 teacher 實例已經(jīng)被外層修改掉了成員變量。

為了解決這個問題,我們還需要對我們的 Teacher 類進行改造,首先我們可以想到的就是需要將 students 和 metadata 兩個成員變量不能直接返回給外層,否則外層的修改會直接影響到我們的不可變類,那么我們就可以修改 getter 方法,拷貝一下成員變量進行返回,而不是直接返回,修改代碼如下

??public?List<String>?getStudents()?{
????return?new?ArrayList<>(students);
????//return?students;
??}
????public?Map<String,?String>?getMetadata()?{
????return?new?HashMap<>(metadata);
??//return?metadata;
??}

我們再次運行上面的測試代碼,可以看到這次的返回數(shù)據(jù)如下,這次我們的 students 和 metadate 成員變量并沒有被外層修改掉了。但是我們的 address 成員變量還是有問題,沒關(guān)系,我們接著往下看。

很自然的為了解決 address 的問題,我們想到了也是進行一個拷貝,再調(diào)用 getter 方法的時候返回一個拷貝對象,而不是直接返回成員變量。那我們就需要改造 Address 類,將其變成 Cloneable 的即可,我們實現(xiàn) 接口,然后覆蓋一個 clone 方法,代碼如下

package?com.example.demo.immutable;

public?class?Address?implements?Cloneable{
??...//?省略
??@Override
??public?Address?clone()?{
????try?{
??????return?(Address)?super.clone();
????}?catch?(CloneNotSupportedException?e)?{
??????throw?new?AssertionError();
????}
??}
}

再修改 Teacher 的 getAddress 方法

??public?Address?getAddress()?{
??//return?address;
????return?address.clone();
??}

接下來我們再運行一下測試代碼,結(jié)果如下,可以看到這次我們的 teacher 實例的成員變量并沒有被修改掉了,至此我們完成了一個不可變對象的創(chuàng)建!

String 的實現(xiàn)

前面我們看的是自定義實現(xiàn)不可變類的操作,接下來我們簡單看一下 String 類是如何實現(xiàn)不可變的,通過源碼我們可以看到 String 也使用了關(guān)鍵字 final 來避免被子類繼承,以及對應(yīng)存放具體值的成員變量也使用了 final 關(guān)鍵字。

并且對外提供的方法 substring 也是通過復(fù)制的形式對外提供的新的 String 對象。

到此這篇關(guān)于詳解Java如何實現(xiàn)一個像String一樣不可變的類的文章就介紹到這了,更多相關(guān)Java不可變的類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java集合 LinkedList的原理及使用詳解

    Java集合 LinkedList的原理及使用詳解

    這篇文章主要介紹了Java集合 LinkedList的原理及使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • spring的@Transactional注解用法解讀

    spring的@Transactional注解用法解讀

    這篇文章主要介紹了spring的@Transactional注解用法解讀,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • Java鏈接redis_動力節(jié)點Java學院整理

    Java鏈接redis_動力節(jié)點Java學院整理

    這篇文章主要介紹了Java鏈接redis,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • MyBatis中#{}占位符與${}拼接符的用法說明

    MyBatis中#{}占位符與${}拼接符的用法說明

    這篇文章主要介紹了MyBatis中#{}占位符與${}拼接符的用法說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • 詳解Idea中HTTP Client請求測試工具的使用

    詳解Idea中HTTP Client請求測試工具的使用

    今天抽空給大家分享Idea中HTTP Client請求測試工具的使用,小編在這建議使用HTTP Client的Idea版本最好在2018以上,不然的話體驗不是多好,今天就給大家介紹Idea中HTTP Client怎么使用的,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • 淺談Java中Lock和Synchronized的區(qū)別

    淺談Java中Lock和Synchronized的區(qū)別

    這篇文章主要介紹了Java中Lock和Synchronized的區(qū)別,Lock和Synchronized都是java中去用來解決線程安全問題的一個工具,但是具體有什么區(qū)別呢?下面我們一起進入文章了解具體詳細內(nèi)容吧,需要的朋友可以參考一下
    2022-04-04
  • SpringBoot+mybatis+Vue實現(xiàn)前后端分離項目的示例

    SpringBoot+mybatis+Vue實現(xiàn)前后端分離項目的示例

    本文主要介紹了SpringBoot+mybatis+Vue實現(xiàn)前后端分離項目的示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 簡述mybatis大于小于的轉(zhuǎn)義

    簡述mybatis大于小于的轉(zhuǎn)義

    這篇文章主要介紹了mybatis大于小于的轉(zhuǎn)義以及xml中常用轉(zhuǎn)義字符,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • java如何獲取request中json數(shù)據(jù)

    java如何獲取request中json數(shù)據(jù)

    這篇文章主要給大家介紹了關(guān)于java如何獲取request中json數(shù)據(jù)的相關(guān)資料,文中通過代碼示例以及圖文將獲取的方法介紹的非常詳細,對大家學習或者使用java具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • Java設(shè)計模式之工廠方法模式詳解

    Java設(shè)計模式之工廠方法模式詳解

    工廠方法模式(FACTORY METHOD)是一種常用的類創(chuàng)建型設(shè)計模式,此模式的核心精神是封裝類中變化的部分,提取其中個性化善變的部分為獨立類,通過依賴注入以達到解耦、復(fù)用和方便后期維護拓展的目的。它的核心結(jié)構(gòu)有四個角色,分別是抽象工廠、具體工廠、抽象產(chǎn)品、具體產(chǎn)品
    2022-08-08

最新評論

商城县| 深州市| 奈曼旗| 宿迁市| 东丰县| 安多县| 社旗县| 江陵县| 翼城县| 太和县| 行唐县| 朝阳县| 南江县| 马公市| 蒙城县| 邵阳县| 定南县| 五河县| 临江市| 浙江省| 鄂州市| 晴隆县| 新乐市| 灵宝市| 稻城县| 内江市| 泰宁县| 方正县| 札达县| 新兴县| 马龙县| 高密市| 星座| 延安市| 浪卡子县| 乐都县| 永兴县| 泸溪县| 高邑县| 中山市| 苍南县|