日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
Java中如何實(shí)現(xiàn)一個(gè)像String一樣不可變的類(lèi)?

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

專(zhuān)注于為中小企業(yè)提供網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)崇明免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了千余家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

特性

在手動(dòng)編寫(xiě)代碼之前,我們先了解一下不可變類(lèi)都有哪些特性,

定義類(lèi)的時(shí)候需要使用final? 關(guān)鍵字進(jìn)行修飾:之所以使用 final 進(jìn)行修飾是因?yàn)檫@樣可以避免被其他類(lèi)繼承,一旦有了子類(lèi)繼承就會(huì)破壞父類(lèi)的不可變性機(jī)制;

成員變量需要使用fina?l 關(guān)鍵詞修飾,并且需要是 private 的:避免屬性被外部修改;

成員變量不可提供setter? 方法,只能提供 getter 方法:避免被外部修改,并且避免返回成員變量本身;

提供所有字段的構(gòu)造函數(shù);

實(shí)操

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

這里我們定義一個(gè) Teacher? 類(lèi)來(lái)測(cè)試一下,按照我們上面提到的幾點(diǎn),我們給類(lèi)和屬性的定義都加上 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 students;
private final Address address;
private final Map metadata;

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

public String getName(){
return name;
}


public List getStudents(){
return students;
}

public Address getAddress(){
return address;
}

public Map 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ù)三下。為了回答這個(gè)問(wèn)題,我們看下下面的測(cè)試代碼。

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;

/**
*

* Function:

* Author:@author Silence

* Date:2022-11-22 21:17

* Desc:無(wú)

*/
public class ImmutableDemo {

public static void main(String[] args){
List students = new ArrayList<>();
students.add("鴨血粉絲 1");
students.add("鴨血粉絲 2");
students.add("鴨血粉絲 3");
Address address = new Address();
address.setCountry("中國(guó)");
address.setCity("深圳");
Map 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());
}

}

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

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

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

我們?cè)俅芜\(yùn)行上面的測(cè)試代碼,可以看到這次的返回?cái)?shù)據(jù)如下,這次我們的 students? 和 metadate? 成員變量并沒(méi)有被外層修改掉了。但是我們的 address 成員變量還是有問(wèn)題,沒(méi)關(guān)系,我們接著往下看。

很自然的為了解決 address? 的問(wèn)題,我們想到了也是進(jìn)行一個(gè)拷貝,再調(diào)用 getter? 方法的時(shí)候返回一個(gè)拷貝對(duì)象,而不是直接返回成員變量。那我們就需要改造 Address? 類(lèi),將其變成 Cloneable? 的即可,我們實(shí)現(xiàn) 接口,然后覆蓋一個(gè) 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();
}

接下來(lái)我們?cè)龠\(yùn)行一下測(cè)試代碼,結(jié)果如下,可以看到這次我們的 teacher 實(shí)例的成員變量并沒(méi)有被修改掉了,至此我們完成了一個(gè)不可變對(duì)象的創(chuàng)建!

String 的實(shí)現(xiàn)

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

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

注意阿粉這里的 JDK 版本是 19 所以可能大家版本不一致具體的實(shí)現(xiàn)不太一樣,但是本質(zhì)上都是一樣的。


網(wǎng)站欄目:Java中如何實(shí)現(xiàn)一個(gè)像String一樣不可變的類(lèi)?
本文鏈接:http://m.5511xx.com/article/dhgpdgc.html