程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java不可變類機制淺析

Java不可變類機制淺析

編輯:關於JAVA

Java不可變類機制淺析。本站提示廣大學習愛好者:(Java不可變類機制淺析)文章只能為提供參考,不一定能成為您想要的結果。以下是Java不可變類機制淺析正文


 不可變類(Immutable Class):所謂的不可變類是指這個類的實例一旦創立完成後,就不能改動其成員變量值。如JDK外部自帶的很多不可變類:Interger、Long和String等。

可變類(Mutable Class):絕對於不可變類,可變類創立實例後可以改動其成員變量值,開發中創立的大局部類都屬於可變類。

不可變類的特性對JAVA來說帶來怎樣的益處?

1)線程平安:不可變對象是線程平安的,在線程之間可以互相共享,不需求應用特殊機制來保證同步問題,由於對象的值無法改動。可以降低並發錯誤的能夠性,由於不需求用一些鎖機制等保證內存分歧性問題也增加了同步開支。

2)易於結構、運用和測試。

不可變類的設計准繩

如何在Java中寫出Immutable的類?要寫出這樣的類,需求遵照以下幾個准繩:

1)immutable對象的形態在創立之後就不能發作改動,任何對它的改動都應該發生一個新的對象。

2)Immutable類的一切的成員都應該是private final的。經過這種方式保證成員變量不可改動。但只做到這一步還不夠,由於假如成員變量是對象,它保管的只是援用,有能夠在內部改動其援用指向的值,所以第5點補償這個缺乏

3)對象必需被正確的創立,比方:對象援用在對象創立進程中不能洩露。4)只提供讀取成員變量的get辦法,不提供改動成員變量的set辦法,防止經過其他接口改動成員變量的值,毀壞不可變特性。

5)類應該是final的,保證類不被承繼,假如類可以被承繼會毀壞類的不可變性機制,只需承繼類掩蓋父類的辦法並且承繼類可以改動成員變量值,那麼一旦子類以父類的方式呈現時,不能保證以後類能否可變。

6)假如類中包括mutable類對象,那麼前往給客戶端的時分,前往該對象的一個深拷貝,而不是該對象自身(該條可以歸為第一條中的一個特例)

假如將結構器傳入的對象直接賦值給成員變量,還是可以經過對傳入對象的修正進而招致改動外部變量的值。例如:

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

這種方式不能保證不可變性,myArray和array指向同一塊內存地址,用戶可以在ImmutableDemo之外經過修正array對象的值來改動myArray外部的值。為了保證外部的值不被修正,可以采用深度copy來創立一個新內存保管傳入的值。正確做法:

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

String類的不可變完成

String對象在內存創立後就不可改動,不可變對象的創立普通滿足以上准繩,我們看看String代碼是如何完成的。

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類的設計契合下面總結的不變類型的設計准繩。雖然String對象將value設置為final,並且還經過各種機制保證其成員變量不可改動。但是還是可以經過反射機制改動其值。例如:

String s = "Hello World"; //創立字符串"Hello World", 並賦給援用s
System.out.println("s = " + s);   
//獲取String類中的value字段
Field valueFieldOfString = String.class.getDeclaredField("value");
valueFieldOfString.setAccessible(true); //改動value屬性的訪問權限
char[] value = (char[]) valueFieldOfString.get(s);
value[5] = '_'; //改動value所援用的數組中的第5個字符
System.out.println("s = " + s);   //Hello_World打印後果為:
s = Hello World
s = Hello_World

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

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

以上所述是給大家引見的Java不可變類機制淺析,希望對大家有所協助,假如大家有任何疑問歡送給我留言,會及時回復大家的!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved