⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 immut.html

📁 Concurrent Programming in Java
💻 HTML
字号:
<html><!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><html> <head><title>Immutable Objects</title></head><BODY bgcolor=#ffffee vlink=#0000aa link=#cc0000><h1>Immutable Objects</h1>One sure way to avoid interference or the need to synchronizeactivities with respect to changes in objects is <em>not</em> tochange the objects.<p> As people who write functional programs (e.g., in ML) know,programs are much simpler to understand if existing objects are neverchanged, but instead new ones are continually created, during thecourse of any computation.  But such programs are generally slower,harder and less natural for most people to write, and, mostimportantly, much less able to deal with interaction (e.g., via userinterfaces), than those involving objects that do change state.<p>However, selective use of statelessness and immutability isa useful tool in concurrent OO programming, potentiallyapplicable in situations including:<ul>  <li> When objects are used exclusively to represent values (i.e.,       serve as simple Abstract Data Types -- see, e.g., <a       href="javascript:if(confirm('http://g.oswego.edu/dl/oosdw3/ch16/ch16.html  \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address.  \n\nDo you want to open it from the server?'))window.location='http://g.oswego.edu/dl/oosdw3/ch16/ch16.html'" tppabs="http://g.oswego.edu/dl/oosdw3/ch16/ch16.html">OOSD</a>). For       example, colors (java.awt.Color), numbers (java.lang.Integer),       strings (java.lang.String).  <li> When different classes, supporting different usages, can be       arranged for the immutable versus updatable versions       of some concept. For example java.lang.String is immutable,       while java.lang.StringBuffer is updatable.  <li> When the need to create different variants, versions, or states       of an object by partial copying is relatively rare.  <li> When the costs of copying, etc., outweigh the benefits of never       needing to synchronize on changes. (In particular, when copies       can sometimes be avoided via algorithmic cleverness.)  <li> When you'd like to have multiple objects represent the same       values and/or perform the same functionality without knowing       or caring about exactly which object you have at any given time.       (As in the <A HREF="javascript:if(confirm('http://www.omg.org/  \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address.  \n\nDo you want to open it from the server?'))window.location='http://www.omg.org/'" tppabs="http://www.omg.org/">CORBA</A> notion of       a <em>pseudo-objects</em> which may be implemented either       via calls to remote objects or to local versions with the same behavior.)  <li> When you need <em>transient</em> immutability; i.e., you need       to ``turn off'' updatability for only some       particular purposes (e.g., the duration of a method call).</ul>By far the most common cases where one or more of these considerationsapply are with ordinary ``data structure'' classes -- tables, lists,and so on, especially under the need for transient immutability. Forexample, a method may be sent a modifiable list of some sort with theintent that it traverse the list without otherwise modifying it, andwithout the client having any good recourse about what to do if themethod does modify it.<p> Writing classes that are strictly immutable is easy (just don'tlist any methods that change any instance variables or cause others tochange theirs) and not discussed here.<p> However, designing Java classes to support <em>transient</em>immutability takes some set-up.  The recipe is:<ol><li> (Optional) Use a convention to provide a name for this immutablity     property. For example, define empty interface     <CODE>Immutable</CODE> so that by convention, such classes     declare <CODE>implements Immutable</CODE>.<li> Define a base interface describing some non-mutative functionality.      The listed methods may include those that construct new objects      that are the same as the target object except for some stated      difference. (For example, for a Sting class, returns a new      string which is the same as the current one except that it      has a newline appended.)<li> Define a subinterface that supports additional update methods.<li> Implement the updatable interfaces via normal classes.<li> Implement the immutable versions as follows:    <ul>      <li> Declare that they are  are <CODE>final</CODE> classes          and support <EM>only</EM> the operations described in the          interface. The use of <CODE>final</CODE> means that when you          think you have an immutable object, you really do -- it's          not of some subclass that supports mutable operations as          well.      <li> Define them to have an instance variable, say, <code>delegate</code>           of the base interface type.      <li> Define each method to simply forward the message to           <code>delegate</code>. However, for the sake of efficiency,            methods that would otherwise cause the construction of            new objects can instead sometimes be implemented using lazy updates            and similar tricks.      <li> Supply a constructor that takes an existing object to            be held immutably in this fashion.      <li> (Optionally) Also supply a constructor that            builds one of these delegates from scratch if none is supplied.    </ul></ol>For a framework of data structure classes designed in this fashion,see the <a href="javascript:if(confirm('http://g.oswego.edu/dl/classes/collections  \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address.  \n\nDo you want to open it from the server?'))window.location='http://g.oswego.edu/dl/classes/collections'" tppabs="http://g.oswego.edu/dl/classes/collections">collections package</a>.<p>To apply these steps to a simple Accounts class:<pre>public interface Immutable {}public interface Account {  public double balance();}public interface UpdatableAccount extends Account {  public void deposit(double Amount) throws InsufficientFunds;  public void withdraw(double Amount) throws InsufficientFunds;}public class UpdatableAccountImplementation implements UpdatableAccount {  private double balance_;  public UpdatableAccountImplementation(double initialBalance) {    balance_ = initialBalance;  }  public synchronized double balance() { return balance_; }  public synchronized void deposit(double amount) throws InsufficientFunds {   if (amount >= 0.0 || balance_ &gt;= -amount) balance_ += amount;   else throw new InsufficientFunds();  }  public synchronized void withdraw(double amount) throws InsufficientFunds {    deposit(-amount);  }} public final class ImmutableAccount implements Account, Immutable {   Account acct_;   // create a fresh immutable account   ImmutableAccount(double initialBalance) {     acct_ = new UpdatableAccountImplementation(initialBalance);   }   // hold an exisiting account immutably   ImmutableAccount(Account acct) {     acct_ = acct;   }   public double balance() { return acct_.balance(); }}</pre>These classes could be used, for example in:<pre>class AccountRecorder {  public void recordBalance(Account a) { System.out.println(a.balance()); }  ...}class AccountHolder {  UpdatableAccount myAccount_;  AccountRecorder recorder_;  public AccountHolder(AccountRecorder r) { recorder_ = r; ... }  void acceptMoney(double amount) {    try {     myAccount.deposit(amount);      recorder_.recordBalance(new ImmutableAccount(myAccount_)); // (*)    }    catch (InsufficientFunds ex) {     System.out.println("Cannot accept negative amount!");  }}     </pre>The use of the immutable wrapper at line <code>(*)</code> might inthis example, be an unnecessary precaution. On the other hand,the precaution does guard against what might happen ifsomeone were to write subclass:<pre>class EvilAccountRecorder extends AccountRecorder {  private double embezzlement_;  ...  public void recordBalance(Account a) {    if (a instanceof UpdatableAccount) {      UpdatableAccount u = (UpdatableAccount)a;      try {        u.withdraw(10.00);        embezzlement += 10.00;       }      catch (InsufficientFunds quietlyignore) {}    }    super.recordBalance(a);  }}</pre><p><a href="aopintro.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/aopintro.html">[Concurrent Programming in Java]</a><hr><address><A HREF="javascript:if(confirm('http://g.oswego.edu/dl  \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address.  \n\nDo you want to open it from the server?'))window.location='http://g.oswego.edu/dl'" tppabs="http://g.oswego.edu/dl">Doug Lea</A></address><!-- hhmts start -->Last modified: Tue Feb 20 06:28:59 EST 1996<!-- hhmts end --></body> </html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -