一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - JAVA不可變類(immutable)機制與String的不可變性(推薦)

JAVA不可變類(immutable)機制與String的不可變性(推薦)

2020-06-01 13:41JohnZheng JAVA教程

這篇文章主要介紹了JAVA不可變類(immutable)機制與String的不可變性(推薦)的相關資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下

一、不可變類簡介

不可變類:所謂的不可變類是指這個類的實例一旦創建完成后,就不能改變其成員變量值。如JDK內部自帶的很多不可變類:Interger、Long和String等。
可變類:相對于不可變類,可變類創建實例后可以改變其成員變量值,開發中創建的大部分類都屬于可變類。

二、不可變類的優點

說完可變類和不可變類的區別,我們需要進一步了解為什么要有不可變類?這樣的特性對JAVA來說帶來怎樣的好處?

1.線程安全

不可變對象是線程安全的,在線程之間可以相互共享,不需要利用特殊機制來保證同步問題,因為對象的值無法改變??梢越档筒l錯誤的可能性,因為不需要用一些鎖機制等保證內存一致性問題也減少了同步開銷。

2.易于構造、使用和測試

3....

三、不可變類的設計方法

對于設計不可變類,個人總結出以下原則:

1. 類添加final修飾符,保證類不被繼承。

如果類可以被繼承會破壞類的不可變性機制,只要繼承類覆蓋父類的方法并且繼承類可以改變成員變量值,那么一旦子類以父類的形式出現時,不能保證當前類是否可變。

2. 保證所有成員變量必須私有,并且加上final修飾

通過這種方式保證成員變量不可改變。但只做到這一步還不夠,因為如果是對象成員變量有可能再外部改變其值。所以第4點彌補這個不足。

3. 不提供改變成員變量的方法,包括setter

避免通過其他接口改變成員變量的值,破壞不可變特性。

4.通過構造器初始化所有成員,進行深拷貝(deep copy)

如果構造器傳入的對象直接賦值給成員變量,還是可以通過對傳入對象的修改進而導致改變內部變量的值。例如:

?
1
2
3
4
5
6
public final class ImmutableDemo {
private final int[] myArray;
public ImmutableDemo(int[] array) {
this.myArray = array; // wrong
}
}

這種方式不能保證不可變性,myArray和array指向同一塊內存地址,用戶可以在ImmutableDemo之外通過修改array對象的值來改變myArray內部的值。

為了保證內部的值不被修改,可以采用深度copy來創建一個新內存保存傳入的值。正確做法:

?
1
2
3
4
5
6
public final class MyImmutableDemo {
private final int[] myArray;
public MyImmutableDemo(int[] array) {
this.myArray = array.clone();
}
}

5. 在getter方法中,不要直接返回對象本身,而是克隆對象,并返回對象的拷貝

這種做法也是防止對象外泄,防止通過getter獲得內部可變成員對象后對成員變量直接操作,導致成員變量發生改變。

四、String對象的不可變性

string對象在內存創建后就不可改變,不可變對象的創建一般滿足以上5個原則,我們看看String代碼是如何實現的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
{
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
/** Cache the hash code for the string */
private int hash; // Default to 0
....
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length); // deep copy操作
}
...
public char[] toCharArray() {
// Cannot use Arrays.copyOf because of class initialization order issues
char result[] = new char[value.length];
System.arraycopy(value, 0, result, 0, value.length);
return result;
}
...
}

如上代碼所示,可以觀察到以下設計細節:

1.String類被final修飾,不可繼承

2.string內部所有成員都設置為私有變量

3.不存在value的setter

4.并將value和offset設置為final。

5.當傳入可變數組value[]時,進行copy而不是直接將value[]復制給內部變量.

6.獲取value時不是直接返回對象引用,而是返回對象的copy.

這都符合上面總結的不變類型的特性,也保證了String類型是不可變的類。

五、String對象的不可變性的優缺點

從上一節分析,String數據不可變類,那設置這樣的特性有什么好處呢?我總結為以下幾點:

1.字符串常量池的需要.

字符串常量池可以將一些字符常量放在常量池中重復使用,避免每次都重新創建相同的對象、節省存儲空間。但如果字符串是可變的,此時相同內容的String還指向常量池的同一個內存空間,當某個變量改變了該內存的值時,其他遍歷的值也會發生改變。所以不符合常量池設計的初衷。

2. 線程安全考慮。

同一個字符串實例可以被多個線程共享。這樣便不用因為線程安全問題而使用同步。字符串自己便是線程安全的。

3. 類加載器要用到字符串,不可變性提供了安全性,以便正確的類被加載。譬如你想加載java.sql.Connection類,而這個值被改成了myhacked.Connection,那么會對你的數據庫造成不可知的破壞。

4. 支持hash映射和緩存。

因為字符串是不可變的,所以在它創建的時候hashcode就被緩存了,不需要重新計算。這就使得字符串很適合作為Map中的鍵,字符串的處理速度要快過其它的鍵對象。這就是HashMap中的鍵往往都使用字符串。

缺點:

1.如果有對String對象值改變的需求,那么會創建大量的String對象。

六、String對象的是否真的不可變

雖然String對象將value設置為final,并且還通過各種機制保證其成員變量不可改變。但是還是可以通過反射機制的手段改變其值。例如:

?
1
2
3
4
5
6
7
8
9
10
11
12
//創建字符串"Hello World", 并賦給引用s
String s = "Hello World";
System.out.println("s = " + s); //Hello World
//獲取String類中的value字段
Field valueFieldOfString = String.class.getDeclaredField("value");
//改變value屬性的訪問權限
valueFieldOfString.setAccessible(true);
//獲取s對象上的value屬性的值
char[] value = (char[]) valueFieldOfString.get(s);
//改變value所引用的數組中的第5個字符
value[5] = '_';
System.out.println("s = " + s); //Hello_World

打印結果為:

?
1
2
s = Hello World
s = Hello_World

發現String的值已經發生了改變。也就是說,通過反射是可以修改所謂的“不可變”對象的

總結

不可變類是實例創建后就不可以改變成員遍歷的值。這種特性使得不可變類提供了線程安全的特性但同時也帶來了對象創建的開銷,每更改一個屬性都是重新創建一個新的對象。JDK內部也提供了很多不可變類如Integer、Double、String等。String的不可變特性主要為了滿足常量池、線程安全、類加載的需求。合理使用不可變類可以帶來極大的好處。

以上所述是小編給大家介紹的JAVA不可變類(immutable)機制與String的不可變性(推薦),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!

原文鏈接:http://www.cnblogs.com/jaylon/p/5721571.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日本中文字幕不卡在线一区二区 | 大学生情侣在线 | 九九99热久久精品在线6 | 青青青国产 | 国产精品久久久久久久人人看 | 青草草在线观看 | 嗯啊好大好粗 | 99久久香蕉国产线看观香 | 亚洲国产精品一区二区久久 | 欧美国产日本高清不卡 | 亚洲va欧美va天堂v国产综合 | 性绞姿始动作动态图 | 精品淑女少妇AV久久免费 | 国产最新进精品视频 | 男人j放进女人的p视频免费 | 5g在线观看 | 大胆人gogo888体艺术在线 | 激情另类国内一区二区视频 | 91丝袜足控免费网站xx | 色漫在线观看 | 欧美一级在线全免费 | 男人j进女屁股视频在线观看 | 公交车高h| youjizzxxx在线观看 | 91精品国产色综合久久 | 男人躁女人p | 亚洲欧美日韩综合在线 | www国产精品 | 麻豆夏晴子 | jiizz亚洲护士厕所 | 国产一卡二卡3卡4卡四卡在线视频 | 午夜宅男影院 | 2012在线观看免费视频大全 | 亚洲AV午夜福利精品香蕉麻豆 | 希望影院高清免费观看视频 | 午夜伦理yy44008影院 | 韩国最新理论三级在线观看 | 国产精品久久久精品视频 | 天美麻豆 | 天天干天天爽天天操 | www.爱情岛论坛 |