Saturday, December 18, 2010

Synthetic methods in Java

There are two main types of synthetic methods in Java. The first is known as a bridge method. For example, if you have the next code:

class Parent {

void foo(T bar) {}

}

class Child extends Parent {

void foo(Integer bar) {}

}

A compiler will add another method foo to Child:
void foo(Object bar) {
foo((Integer)bar);
}

This is done for backward compatibility as you still should be able to write a code like this:

Parent a = new Child();
Object i = new Integer(1);
a.foo(i);

As you override method in the descendant, Child.foo(Intger bar) is expected to be called on line 3, but without the bridge method it would not be the case. Note that if i is not an integer you will get ClastCastException thrown from the bridge method.


The second case is related to a visibility of private methods of an inner class from an outer class. Consider the following code:


class Outer {

Inner getInner() {
return new Inner();
}

private class Inner {
private Inner() {
}
}

}

As you know Inner will be compiled to a separate class1, so to make its private entities available from Outer the compiler creates a synthetic method in outer class that constructs a new Inner and call this new method from getInner(). Such synthetic members are only meant to be accessed by trusted code generated by the compiler.

1As first versions of JVM did not support inner classes, developers had to introduce a hack that would allow nested classes and be backward compatible, that's why you can observe such behavior