Joshua Bloch’s JavaOne’06 presentation on Effective Java Reloaded previewed his second edition of the most famous Java best practice guide in the Java developer community. Finally, the book is hitting the market on Nov 9, 2007 and it is available for Pre-Order from Amazon.com. But, you can start using some of these best practices today. Google Collections is home for some of these Java programming best practices. Not sure, when these features would become part of core library. They are simple to use and provide rich data structures and complement the Java collections library. Go for it, though its still in its alpha release. Google Collections is a natural home for these developer savvy features until we see them adopted in the core library. After all, Joshua is Google’s Chief Java Architect.

Possibly Related Posts:


Synthetic methods are often referred to as bridge methods in Java generics world. These methods are created by the Java compiler as a result of type erasure when the signature of the inherited methods change when a type extends or implements parameterized classes or interfaces. The compiler generates synthetic methods in subtypes of parameterized supertypes to make sure that subtyping works as expected.

For instance, let us try to extend the Lock interface defined in concurrency package and define an extended lock method which takes a type parameter. We use the hidden “-XD-printflat” compiler option to generate the java files after type erasure.

javac -d tmp -XD-printflat LockExImpl.java

LockEx interface

public interface LockEx extends java.util.concurrent.locks.Lock {
  //extended lock method
  void lockEx(T t);
}

LockExImpl Before Erasure

final class LockExImpl<T> extends java.util.concurrent.locks.ReentrantLock
			implements LockEx<LockExImpl>  {
  public void lockEx(LockExImpl mutex) {
    throw new UnsupportedOperationException("Not supported yet.");
  }
}

LockExImpl After Erasure

final class LockExImpl extends java.util.concurrent.locks.ReentrantLock
                                     implements LockEx {
  LockExImpl() {
    super();
  }

  public void lockEx(LockExImpl mutex) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  /*synthetic*/

  public void lockEx(Object x0) {
    this.lockEx((LockExImpl)x0);
  }
}

Possibly Related Posts:


I was reading a recent blog entry from A. Sundararajan which uncovers one of the hidden options used to be available only for debugging Java compiler. This option is an undocumented feature which explains the underpinnings behind some of the various language features introduced in JDK1.5. OpenJDK provides an opportunity to learn the intricacies of Java compiler implementation. Sundararajan’s blog uncovers the implementation of inner classes in Java. I am going to use the samples which I used in my JDK1.5 article on developer.com. The bottom line is you would see how the new language features are implemented using the plain old java syntax (POJS) and sometimes these are verbose and ugly (See how Enums are compiled). This a good example of abstraction where the complexity is hidden by the compiler. The transformations are fairly straightforward. I will leave up to the reader to dig into this.

Here is how you use the hidden option -XD to printflat when compiling a Java program.

javac -d tmp -XD-printflat EnumFacility.java

This will create the files in tmp directory. Make sure you don’t try compiling a file from the same directory. It would fail to overwrite the input file.

Generic Class

public class C<T1, T2> {
  private T1 type1;
  private T2 type2;

  public C(T1 type1, T2 type2) {
    this.type1 = type1;
    this.type2 = type2;
  }

  public T1 getType1() {
    return this.type1;
  }

  public T2 getType2() {
    return this.type2;
  }

  public static void main(String args[]) {
    C<String, Integer> cStrInt = new C<String, Integer>("one", 1);
    String type1StrInt = cStrInt.getType1();
    Integer type2SI    = cStrInt.getType2();
    C<Integer, Boolean> cIntBool = new C<Integer, Boolean>(1, true);
    Integer type1IntStr = cIntBool.getType1();
    Boolean type2IntStr = cIntBool.getType2();
  }
}

Generic Class (with printflat)

public class C {
  private Object type1;
  private Object type2;

  public C(Object type1, Object type2) {
    super();
    this.type1 = type1;
    this.type2 = type2;
  }

  public Object getType1() {
    return this.type1;
  }

  public Object getType2() {
    return this.type2;
  }

  public static void main(String[] args) {
    C cStrInt = new C("one", Integer.valueOf(1));
    String type1StrInt = (String)cStrInt.getType1();
    Integer type2SI = (Integer)cStrInt.getType2();
    C cIntBool = new C(Integer.valueOf(1), Boolean.valueOf(true));
    Integer type1IntStr = (Integer)cIntBool.getType1();
    Boolean type2IntStr = (Boolean)cIntBool.getType2();
  }
}

Generic Interface

public interface I<T> {
  public T getConnectionPool();
  public void releaseConnectionPool(T connectionPool);
}

Generic Interface (with printflat)

public interface I {
  public Object getConnectionPool();
  public void releaseConnectionPool(Object connectionPool);
}

Generic Method

public class M {
  public static <T extends Comparable<T>> T minimum(T a, T b) {
    if(a.compareTo(b) <= 0) return a;
    else return b;
}
  public static void main(String&#91;&#93; args) {
    Integer b1  = new Integer(2);
    Integer b2  = new Integer(5);
    Integer min = minimum(b1, b2);
    System.out.println("Minimum of (2,5) : " + min);
  }
}
&#91;/sourcecode&#93;
<h3>Generic Method (with printflat)</h3>

public class M {
  public M() {
    super();
  }

  public static Comparable minimum(Comparable a, Comparable b) {
    if (a.compareTo(b) <= 0) return a; else return b;
  }

  public static void main(String&#91;&#93; args) {
    Integer b1 = new Integer(2);
    Integer b2 = new Integer(5);
    Integer min = (Integer)minimum(b1, b2);
    System.out.println("Minimum of (2,5) : " + min);
  }
}
&#91;/sourcecode&#93;
<h3>Generic Collections</h3>

public class CollectionFiltering {
  static void purgeFromCollection(Collection<String> c) {
    for (Iterator<String> i = c.iterator(); i.hasNext(); ) {
      if(i.next().length() == 4)
      i.remove();
    }
    System.out.println(c);
  }

  public static void main(String args[]) {
    List<String> arrayList = new ArrayList<String>();
    arrayList.add(new String("One"));
    arrayList.add(new String("Two"));
    arrayList.add(new String("Three"));
    arrayList.add(new String("Four"));
    System.out.println(arrayList);
    purgeFromCollection(arrayList);
  }
}

Generic Collections (with printflat)

public class CollectionFiltering {
  public CollectionFiltering() {
    super(); 
  }

  static void purgeFromCollection(Collection c) {
    for (Iterator i = c.iterator(); i.hasNext(); ) {
      if (((String)i.next()).length() == 4) i.remove();
    }
    System.out.println(c);
  }

  public static void main(String[] args) {
    List arrayList = new ArrayList();
    arrayList.add(new String("One"));
    arrayList.add(new String("Two"));
    arrayList.add(new String("Three"));
    arrayList.add(new String("Four"));
    System.out.println(arrayList);
    purgeFromCollection(arrayList);
  }
}

Enums

public class EnumFacility {
  enum Continent { africa , asia, europe, north_america, oceania, south_america };

  public static void main(String args[]) {
    for ( Continent c : Continent.values() ) {
    // switch on enum
      switch(c) {
        case africa:
          System.out.println("in africa.");
          break;
        case asia:
          System.out.println("in asia.");
          break;
        case europe:
          System.out.println("in europe.");
          break;
        case north_america:
          System.out.println("in north_america.");
          break;
        case oceania:
          System.out.println("in oceania.");
          break;
        case south_america:
          System.out.println("in south_america.");
          break;
      }
    }
  }
}

Enums (with printflat)

public class EnumFacility {
  {
  }

  public EnumFacility() {
    super();
  }
  {
  }
  {
  }

  public static void main(String[] args) {
    for (EnumFacility$Continent[] arr$ = EnumFacility$Continent.values(), len$ = arr$.length, i$ = 0; i$ &lt; len$; ++i$) {
      EnumFacility$Continent c = arr$[i$];
      {
        switch (EnumFacility$1.$SwitchMap$EnumFacility$Continent[c.ordinal()]) {
          case 1:
            System.out.println("in africa.");
            break;
          case 2:
            System.out.println("in asia.");
            break;
          case 3:
            System.out.println("in europe.");
            break;
          case 4:
            System.out.println("in north_america.");
            break;
          case 5:
            System.out.println("in oceania.");
            break;
          case 6:
            System.out.println("in south_america.");
            break;
        }
      }
    }
  }
}
/*synthetic*/ class EnumFacility$1 {
  /*synthetic*/ static final int[] $SwitchMap$EnumFacility$Continent = new int[EnumFacility.Continent.values().length];
  static {
    try {
      EnumFacility$1.$SwitchMap$EnumFacility$Continent[EnumFacility.Continent.africa.ordinal()] = 1;
    } catch (NoSuchFieldError ex) {
    }
    try {
      EnumFacility$1.$SwitchMap$EnumFacility$Continent[EnumFacility.Continent.asia.ordinal()] = 2;
    } catch (NoSuchFieldError ex) {
    }
    try {
      EnumFacility$1.$SwitchMap$EnumFacility$Continent[EnumFacility.Continent.europe.ordinal()] = 3;
    } catch (NoSuchFieldError ex) {
    }
    try {
      EnumFacility$1.$SwitchMap$EnumFacility$Continent[EnumFacility.Continent.north_america.ordinal()] = 4;
    } catch (NoSuchFieldError ex) {
    }
    try {
      EnumFacility$1.$SwitchMap$EnumFacility$Continent[EnumFacility.Continent.oceania.ordinal()] = 5;
    } catch (NoSuchFieldError ex) {
    }
    try {
      EnumFacility$1.$SwitchMap$EnumFacility$Continent[EnumFacility.Continent.south_america.ordinal()] = 6;
    } catch (NoSuchFieldError ex) {
    }
  }
}
  enum EnumFacility$Continent extends Enum<EnumFacility$Continent> {
    /*public static final*/ africa /* = new EnumFacility$Continent("africa", 0) */,
    /*public static final*/ asia /* = new EnumFacility$Continent("asia", 1) */,
    /*public static final*/ europe /* = new EnumFacility$Continent("europe", 2) */,
    /*public static final*/ north_america /* = new EnumFacility$Continent("north_america", 3) */,
    /*public static final*/ oceania /* = new EnumFacility$Continent("oceania", 4) */,
    /*public static final*/ south_america /* = new EnumFacility$Continent("south_america", 5) */;
    /*synthetic*/ private static final EnumFacility$Continent[] $VALUES = new EnumFacility$Continent[] {EnumFacility$Continent.africa, EnumFacility$Continent.asia, EnumFacility$Continent.europe,  EnumFacility$Continent.north_america, EnumFacility$Continent.oceania, EnumFacility$Continent.south_america};

  public static EnumFacility$Continent[] values() {
    return (EnumFacility$Continent[])$VALUES.clone();
  }

  public static EnumFacility$Continent valueOf(String name) {
    return (EnumFacility$Continent)Enum.valueOf(EnumFacility.Continent.class, name);
  }

  private EnumFacility$Continent(/*synthetic*/ String $enum$name, /*synthetic*/ int $enum$ordinal) {
    super($enum$name, $enum$ordinal);
  }
}

AutoBoxing

public class AutoBoxing {
  static List<Integer> testAutoBoxing(int ii) {
    int i = 0;
    List<Integer> arrayList = new ArrayList<Integer>();
    arrayList.add(++i);
    arrayList.add(new Integer(11));
    arrayList.add(++ii);
    return arrayList;
  }
  public static void main(String args[]) {
    List<Integer> arrayList = testAutoBoxing(110);
    for (Integer i : arrayList)
      System.out.println(i);
  }
}

AutoBoxing (with printflat)

public class AutoBoxing {
  public AutoBoxing() {
    super();
}

  static List testAutoBoxing(int ii) {
    int i = 0;
    List arrayList = new ArrayList();
    arrayList.add(Integer.valueOf(++i));
    arrayList.add(new Integer(11));
    arrayList.add(Integer.valueOf(++ii));
    return arrayList;
  }

  public static void main(String[] args) {
    List arrayList = testAutoBoxing(110);
    for (Iterator i$ = arrayList.iterator(); i$.hasNext(); ) {
      Integer i = (Integer)i$.next();
      System.out.println(i);
    }
  }
}

Enhanced For Statement

public class EnhancedForLoop {
public void testEnhancedForLoop() {
int [] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int sum = 0;
for (int e : a)
sum += e;
System.out.println("Array Sum : " + sum);

}

}

Enhanced For Statement (with printflat)

public class EnhancedForLoop {
  public EnhancedForLoop() {
    super();
  }

  public void testEnhancedForLoop() {
    int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int sum = 0;
    for (int[] arr$ = a, len$ = arr$.length, i$ = 0; i$ &lt; len$; ++i$) {
      int e = arr$[i$];
      sum += e;
    }
    System.out.println("Array Sum : " + sum);
  }
}

Annotations

public class Annotations extends java.lang.Object {
  @SuppressWarnings("deprecation")
  public static void suppressWarnings() {
  //implementation
  }

  @Deprecated
  public static void deprecatedMethod() {
  //implementation
  }

  @Override
  public String toString() {
    return "myOwnImplementation";
  }
}

Annotations (with printflat)

public class Annotations extends java.lang.Object {
  public Annotations() {
    super();
  }

  @SuppressWarnings(value = "deprecation")
  public static void suppressWarnings() {
  }

  @Deprecated()
  public static void deprecatedMethod() {
  }

  @Override()
  public String toString() {
    return "myOwnImplementation";
  }
}

Possibly Related Posts:


Today, I became the proud owner of Alan Greenspan’s The Age of Turbulence: Adventures in a New World. One of my favorite economist writes about the global capitalist economy post 9/11 era. I will add more to this blog as I start reading this economy bible of the 21st century.

Possibly Related Posts:


Welcome to my blog!

Vasundhra

This is my first official blogging on the net. I would like to start my blog by announcing the arrival of our little baby girl Vasundhra on Sep 4. It was awesome to hold her on my hands and welcoming her to this exciting world. Those were miraculous moments. She is just amazing.

Possibly Related Posts:


A Google Code project on detecting singletons in Java code has released its code under Apache Software License. This tool is useful for detecting singletons based on their usage pattern and these patterns are classified as {S, H, M, F}+ingleton. The author introduces these new terminologies based on whether the Singleton is implemented in a classic, helper, method, field based approach. The details of this can be learned from the project website. The output is written to a GraphML format which could be viewed using yEd. This provides a visual representation of singletons and their class references with in a library. This helps developers to fix the unwise way of using Singletons. Here is a sample graph generated from Google Singleton Detector (GSD) for DOM4J library.

GSD generated GraphML representation for DOM4J library

DOM4J GraphML

Singletons were once acclaimed the most used creational design patterns in Java. In the past few years, the usage has been mostly restricted by developers due to its lack of testability in the agile and test driven development world. GSD is at its early stage and has some known limitations. But, this is a good start and niche tool for Java developers to detect singletons in legacy projects and can re-factor if needed.

As defined by GoF in “Design Patterns: Elements of Reusable Object-Oriented Software“, the purpose of Singleton pattern is to ensure a class has only one instance, and provide a global point of access to it. Java has widely adopted this pattern since its inception. There are many arguments which discourage the use of Singletons in Java as they introduce global state which makes it difficult to test. Also, there are some known issues around double-checked locking pattern (DCLP) as there is no guarantee it will work on single or multi processor machines due to out of order writes implemented in JVM prior to 1.5. Double-checked locking idiom was used to avoid expensive synchronizations in the Singleton implementation. But, over time this idiom was proven to be ineffective due to its limitations until the memory model was revised in 1.5. So, the fallback option prior to 1.5 was to accept synchronization or use a static field. The classical singleton implementation in Java using static field is shown below.


public class Singleton {
    private static Singleton _instance;
    private Singleton() {
    }

    public static Singleton Instance() {
        if (_instance == null)
            _instance = new Singleton();
        return _instance;
    }
}

This design ensures that only one instance of Singleton object is ever created. The constructor is declared private and the Instance() method is declared static which creates only one object. This implementation holds good for a single-threaded program. However, when multiple threads are introduced, it is possible that Instance() method to return two different instances of the Singleton object. Synchronizing Instance() method would solve this issue at an extra performance overhead. But, it eliminates our threading issues. The above code is modified to support synchronization.


public class Singleton {
    private static Singleton _instance;
    private Singleton() {
    }

    public static Singleton Instance() {
        if (_instance == null) {
            synchronized (Singleton.class) {
                _instance = new Singleton();
            }
        }
        return _instance;
    }
}

Even with this approach, it is not guaranteed that only one instance of Singleton object would be created because of the blocking nature of synchronization. Both the threads wait to acquire the lock on the object and end up creating two Singleton objects violating the purpose of the pattern. To circumvent this problem, double-checked locking idiom was introduced. The following code shows the double-checked locking implementation of Singleton pattern.


public class Singleton {
    private static Singleton _instance;
    private Singleton() {
    }

    public static Singleton Instance() {
        if (_instance == null) {
            synchronized (Singleton.class) {
                if (_instance == null) {
                    _instance = new Singleton();
                }
            }
        }
        return _instance;
    }
}

DCLP does not allow multiple threads to create multiple Singleton objects. Instead, they are not guaranteed to work on either single or multi-processor machines due to the out of order writes observed in various JVM implementations prior to 1.5. The most obvious reason is that the writes which initialize _instance and write to the _instance field can be reordered by the compiler or the cache, which would have the effect of returning partially constructed Singleton object. This would end up reading an uninitialized object, thus causing the problem in JVMs prior to 1.5.

Under the new memory model implemented as part of JSR 133 suggests making the _instance field volatile should solve the problem of DCLP. This is because the initialization of the Singleton object by the constructing thread happens-before the return of its value by the thread that reads it. This JSR refines the semantics of threads, locks, volatile variables, and final fields. This also proposes a replacement “Initialization On Demand Holder” for DCLP which is thread safe and simpler to use and avoids initialization issues.


private static class LazySingletonHolder {
    public static Singleton _instance = new Singleton();
}

public static Singleton Instance() {
    return LazySingletonHolder._instance;
}

Possibly Related Posts: