麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Java不可變類機(jī)制

2019-11-14 09:16:18
字體:
供稿:網(wǎng)友

不可變類(Immutable Class):所謂的不可變類是指這個(gè)類的實(shí)例一旦創(chuàng)建完成后,就不能改變其成員變量值。如JDK內(nèi)部自帶的很多不可變類:Interger、Long和String等。

可變類(Mutable Class):相對(duì)于不可變類,可變類創(chuàng)建實(shí)例后可以改變其成員變量值,開發(fā)中創(chuàng)建的大部分類都屬于可變類

不可變類的特性對(duì)java來說帶來怎樣的好處?

1)線程安全:不可變對(duì)象是線程安全的,在線程之間可以相互共享,不需要利用特殊機(jī)制來保證同步問題,因?yàn)閷?duì)象的值無法改變。可以降低并發(fā)錯(cuò)誤的可能性,因?yàn)椴恍枰靡恍╂i機(jī)制等保證內(nèi)存一致性問題也減少了同步開銷。

2)易于構(gòu)造、使用和測(cè)試。

不可變類的設(shè)計(jì)原則

如何在Java中寫出Immutable的類?要寫出這樣的類,需要遵循以下幾個(gè)原則:

1)immutable對(duì)象的狀態(tài)在創(chuàng)建之后就不能發(fā)生改變,任何對(duì)它的改變都應(yīng)該產(chǎn)生一個(gè)新的對(duì)象。

2)Immutable類的所有的成員都應(yīng)該是PRivate final的。通過這種方式保證成員變量不可改變。但只做到這一步還不夠,因?yàn)槿绻蓡T變量是對(duì)象,它保存的只是引用,有可能在外部改變其引用指向的值,所以第5點(diǎn)彌補(bǔ)這個(gè)不足

3)對(duì)象必須被正確的創(chuàng)建,比如:對(duì)象引用在對(duì)象創(chuàng)建過程中不能泄露。4)只提供讀取成員變量的get方法,不提供改變成員變量的set方法,避免通過其他接口改變成員變量的值,破壞不可變特性。

5)類應(yīng)該是final的,保證類不被繼承,如果類可以被繼承會(huì)破壞類的不可變性機(jī)制,只要繼承類覆蓋父類的方法并且繼承類可以改變成員變量值,那么一旦子類以父類的形式出現(xiàn)時(shí),不能保證當(dāng)前類是否可變。

6)如果類中包含mutable類對(duì)象,那么返回給客戶端的時(shí)候,返回該對(duì)象的一個(gè)深拷貝,而不是該對(duì)象本身(該條可以歸為第一條中的一個(gè)特例)

如果將構(gòu)造器傳入的對(duì)象直接賦值給成員變量,還是可以通過對(duì)傳入對(duì)象的修改進(jìn)而導(dǎo)致改變內(nèi)部變量的值。例如:

public final class ImmutableDemo {      private final int[] myArray;      public ImmutableDemo(int[] array) {          this.myArray = array;		 // wrong      }  }

這種方式不能保證不可變性,myArray和array指向同一塊內(nèi)存地址,用戶可以在ImmutableDemo之外通過修改array對(duì)象的值來改變myArray內(nèi)部的值。為了保證內(nèi)部的值不被修改,可以采用深度copy來創(chuàng)建一個(gè)新內(nèi)存保存?zhèn)魅氲?#20540;。正確做法:

public final class MyImmutableDemo {      private final int[] myArray;      public MyImmutableDemo(int[] array) {          this.myArray = array.clone();       }   }

String類的不可變實(shí)現(xiàn)

String對(duì)象在內(nèi)存創(chuàng)建后就不可改變,不可變對(duì)象的創(chuàng)建一般滿足以上原則,我們看看String代碼是如何實(shí)現(xiàn)的。

public final class String    implements java.io.Serializable, Comparable<String>, CharSequence{    private final char value[]; 	/** The value is used for character storage. */    /** 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;    private int hash; // Default to 0    ....    public String(char value[]) {         this.value = Arrays.copyOf(value, value.length); // deep copy操作     }     public char[] toCharArray() {        char result[] = new char[value.length];        System.arraycopy(value, 0, result, 0, value.length);        return result;    }    ...}

如代碼所示,可以觀察到String類的設(shè)計(jì)符合上面總結(jié)的不變類型的設(shè)計(jì)原則。雖然String對(duì)象將value設(shè)置為final,并且還通過各種機(jī)制保證其成員變量不可改變。但是還是可以通過反射機(jī)制改變其值。例如:

String s = "Hello World"; 	//創(chuàng)建字符串"Hello World", 并賦給引用sSystem.out.println("s = " + s); 	    //獲取String類中的value字段Field valueFieldOfString = String.class.getDeclaredField("value");valueFieldOfString.setaccessible(true); 	//改變value屬性的訪問權(quán)限char[] value = (char[]) valueFieldOfString.get(s);value[5] = '_'; //改變value所引用的數(shù)組中的第5個(gè)字符System.out.println("s = " + s);  			//Hello_World

打印結(jié)果為:

s = Hello World

s = Hello_World

發(fā)現(xiàn)String的值已經(jīng)發(fā)生了改變。也就是說,通過反射是可以修改所謂的“不可變”對(duì)象的。

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


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 国产成人免费精品 | 成人一区三区 | 免费在线观看国产精品 | 欧美一级视频网站 | 激情小说激情电影 | 亚洲人成在线播放网站 | 成人在线观看网 | 小雪奶水翁胀公吸小说最新章节 | 国产剧情在线观看一区二区 | 精品国产成人 | 日韩一级精品 | 国产中出在线观看 | 国产成人精品免费视频大全办公室 | 国产午夜精品一区二区三区免费 | 久草在线视频福利 | 国产精品久久久久久久四虎电影 | 欧美日韩后 | 久久逼逼 | 国产中出在线观看 | 久久成人视屏 | 亚洲片在线观看 | 亚洲白嫩在线观看 | 成人黄视频在线观看 | 免费观看一级黄色片 | 一级电影免费看 | 欧美视频在线一区二区三区 | 国产精品99久久久久久久女警 | 亚洲人成网站免费播放 | 欧美三级一级 | 日韩欧美精品电影 | 国产精品午夜未成人免费观看 | 亚州视频在线 | 黄色av网站免费 | 国产免费v片 | 欧美亚州 | 国产一级毛片在线看 | 国产精品视频免费网站 | av在线播放亚洲 | 中文字幕一区2区 | 99最新网址 | av电影在线网站 |