FileDocCategorySizeDatePackage
Substitute.javaAPI DocExample4871Wed Apr 19 11:21:24 BST 2000None

Substitute.java

/*
 * @(#)Substitute.java	1.2 98/10/01        
 *
 * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of Sun
 * Microsystems, Inc. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sun.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
 * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
 * THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * 
 */

import java.io.*;
import java.util.*;


/**
 * This example shows how to use the readResolve method.
 * This method resolves the object
 * read from the stream before it is returned to the caller.
 * The writeReplacea method allows an object to nominate its 
 * own replacement in the stream before the object is written.  
 *
 * This example creates a symbol class for which only a single instance of
 * each symbol binding exists. The Symbol class defines the
 * readResolve method. A symbol is created from outside using the 
 * symbollookup method, which finds and returns a symbol if one already 
 * exists and creates one, if one does not. This assures uniqueness within
 * one VM. Then, when readResolve is called when the symbol is being read, 
 * a preexisting equivalent Symbol object is substituted from the hashtable 
 * to maintain the unique identity constraint, if such a symbol exists. 
 * Otherwise, the new symbol is added to the hashtable and returned. This 
 * assures uniqueness when we are dealing with more than one VM.
 *
 *
 * How to Run:
 *             Compile this file: javac Substitute.java
 *             Run this file:     java Substitute
 *
 * This will print out a confirmation that the two symbols that were
 * serialized separately but had the same name are indeed the same symbol.
 *
 *
 * Compiled and Tested with JDK1.2
 */

public class Substitute {
   
    /** 
     * Basically, serialize and deserialize two symbols with the same
     *  name and show that they are actually the same symbol.
     */
    public static void main(String args[]) {
	
	// create a few symbols to be serialized
	Symbol s1 = Symbol.symbolLookup("blue");
	Symbol s2 = Symbol.symbolLookup("pink");
	Symbol s3 = Symbol.symbolLookup("blue");

	// use these to deserialize the symbols
	Symbol obj1 = null, obj2 = null, obj3 = null;


	// serialize the symbols
	try {
 	    FileOutputStream fo = new FileOutputStream("symbol.tmp");
	    ObjectOutputStream so = new ObjectOutputStream(fo);
	    so.writeObject(s1);
	    so.writeObject(s2);
	    so.writeObject(s3);
	    so.flush();
	} catch (Exception e) {
	    System.out.println(e);
	    System.exit(1);
	}
	
	// deserialize the symbols
	try {
	    FileInputStream fi = new FileInputStream("symbol.tmp");
	    ObjectInputStream si = new ObjectInputStream(fi);
	    obj1 = (Symbol) si.readObject();
	    obj2 = (Symbol) si.readObject();
	    obj3 = (Symbol) si.readObject();
	} catch (Exception e) {
	    System.out.println(e);
	    System.exit(1);
	}

	// show the uniqueness 
	if (obj1 == obj3) {
	    System.out.println("Symbol1 and Symbol3 are the same!");
	}
    }
}


/** 
 * The class implementing the readResolve method.
 */
class Symbol implements Serializable {

    /**
     * @serial
     */
    String symbolname;

    /* 
     * Hashtable is **static** because we need to use the same one for
     * all symbol objects. 
     */
    static Hashtable ht = new Hashtable();
    
    /** 
     * This method serves as the constructor. It looks in the hashtable and
     * if that symbol exists, will return that symbol... otherwise, will 
     * create a symbol with that name and will add it to the hashtable. This
     * will assure that the symbols are always unique.
     */
    static Symbol symbolLookup(String symname) {
	if (ht.containsKey(symname)) {
	    return (Symbol)(ht.get(symname));
	}
	else {
	    Symbol newSym = new Symbol(symname);
	    ht.put(symname, newSym);
	    return(newSym);
	}
    }

    /** 
     * Private constructor because we want "outsiders" to use 
     *  symbolLookup instead to force uniqueness.
     */
    private Symbol (String name) {
	symbolname = name;
    }

    /** 
     * Deals with the issue of uniqueness when we are dealing with more
     * than one VM by adding the read symbol to the hash table, if it
     * isn't already there.
     */
    public Object readResolve() throws ObjectStreamException {
	if (!ht.containsKey(symbolname))
	    ht.put(symbolname, this);
	return (Symbol) (ht.get(symbolname));
    }
}