Running on Java 24-ea+21-2447 (Preview)
Home of The JavaSpecialists' Newsletter

176The Law of the Xerox Copier

Author: Dr. Heinz M. KabutzDate: 2009-09-22Java Version: 5Category: Tips and Tricks
 

Abstract: Concurrency is easier when we work with immutable objects. In this newsletter, we define another concurrency law, The Law of the Xerox Copier, which explains how we can work with immutable objects by returning copies from methods that would ordinarily modify the state.

 

Welcome to the 176th issue of The Java(tm) Specialists' Newsletter, sent to you from Oslo in Norway. The JavaZone conference is wonderful, with at least one interesting topic per session. There are actually two other talks I'd like to attend when I am speaking tomorrow ...

Thanks for the feedback after my last newsletter, where I showed how to construct objects without calling any constructor. When I wrote the article, I felt it unnecessary to explicitly state that making a linkage to sun.* classes would be a problem for portability of your code, since that is rather obvious. So there, I've said it ... :-)

javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.

The Law of the Xerox Copier

In previous newsletters, we looked at a series of laws to make sense of Java concurrency. Just to remind you, here they are again. In this newsletter, I would like to add a new one to our list, the Law of the Xerox Copier.

  1. The Law of the Sabotaged Doorbell
  2. The Law of the Distracted Spearfisherman
  3. The Law of the Overstocked Haberdashery
  4. The Law of the Blind Spot
  5. The Law of the Leaked Memo
  6. The Law of the Corrupt Politician
  7. The Law of the Micromanager
  8. The Law of Cretan Driving
  9. The Law of Sudden Riches
  10. The Law of the Uneaten Lutefisk
  11. The Law of the Xerox Copier

The Law of the Xerox Copier

Protect yourself by making copies of objects.

At the end of 2008, we found a beautiful house in Crete that we wanted to purchase. We only had one tiny little problem. Houses in general are kind of expensive and I didn't have all that much in my wallet. So we started the long process of begging banks for a loan, which involves giving them reams of paperwork.

You would imagine that it is safe to give a bank your documents, expecting them to look after them until they returned them. Well, the night before the bank was supposed to give back our paperwork, loan denied of course, they were attacked by a mob of angry protesters who completely trashed it, together with our documents. How often does an event like that happen? Fortunately, we had protected our original objects by only giving copies to the loan consultant.

Coming back to concurrency, it is usually a good idea to make your objects as immutable as possible. Instead of then changing the object, we would return a new copy containing the changes.

Immutable objects are always thread safe. We cannot have stale values, race conditions or early writes. According to Brian Goetz, an immutable class is defined as the following:

  • State cannot be modified after construction
  • All the fields are final
  • 'this' reference does not escape during construction

An example of an immutable class is String. Whenever we "modify" it, such as with the + operator or the toUpperCase() method. This causes additional work for the garbage collector, but concurrency is much easier.

In Scala [ISBN 0981531601] , we even have immutable lists. How could that work in Java? Here is an example:

import java.util.Iterator;

public class ImmutableArrayList<E> implements Iterable<E> {
  private final Object[] elements;

  public ImmutableArrayList() {
    this.elements = new Object[0];
  }

  private ImmutableArrayList(Object[] elements) {
    this.elements = elements;
  }

  public int size() {
    return elements.length;
  }

  public ImmutableArrayList<E> add(E e) {
    Object[] new_elements = new Object[elements.length + 1];
    System.arraycopy(elements, 0,
        new_elements, 0, elements.length);
    new_elements[new_elements.length - 1] = e;
    return new ImmutableArrayList<E>(new_elements);
  }

  public Iterator<E> iterator() {
    return new Iterator<E>() {
      private int pos = 0;

      public boolean hasNext() {
        return pos < elements.length;
      }

      public E next() {
        return (E) elements[pos++];
      }

      public void remove() {
        throw new UnsupportedOperationException();
      }
    };
  }
}

Making ArrayList immutable is probably going overboard, a better approach might be to just use the CopyOnWriteArrayList, which also gives us great concurrent performance.

We can use this ImmutableArrayList in a more functional coding approach:

public class ImmutableArrayListTest {
  public static void main(String[] args) {
    ImmutableArrayList<String> ial =
        new ImmutableArrayList<String>();
    ial = ial.add("Heinz").add("Max").add("Kabutz");
    for (Object obj : ial) {
      System.out.println(obj);
    }
  }
}

Making copies of objects has helped me out of a fix many times in the past, where rather complicated concurrency bugs would have been tricky to resolve otherwise.

Kind regards from Oslo

Heinz

 

Comments

We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)

When you load these comments, you'll be connected to Disqus. Privacy Statement.

Related Articles

Browse the Newsletter Archive

About the Author

Heinz Kabutz Java Conference Speaker

Java Champion, author of the Javaspecialists Newsletter, conference speaking regular... About Heinz

Superpack '23

Superpack '23 Our entire Java Specialists Training in one huge bundle more...

Free Java Book

Dynamic Proxies in Java Book
Java Training

We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.

Java Consulting

We can help make your Java application run faster and trouble-shoot concurrency and performance bugs...