153. Getting synthetic and bridge constructs

By using synthetic constructs, we can understand almost any construct that's added by the compiler. More precisely, conforming to the Java language specification: any constructs introduced by a Java compiler that do not have a corresponding construct in the source code must be marked as synthetic, except for default constructors, the class initialization method, and the values and valueOf() methods of the Enum class.

There are different kinds of synthetic constructs (for example, fields, methods, and constructors), but let's take a look at an example of a synthetic field. Let's assume that we have the following class:

public class Melon {
...
public class Slice {}
...
}

Notice that we have an inner class called Slice. When the code is compiled, the compiler will alter this class by adding a synthetic field that's meant to references the top-level class. This synthetic field facilities access to the enclosing class members from a nested class.

In order to check the presence of this synthetic field, let's fetch all the declared fields and count them:

Class<Melon.Slice> clazzSlice = Melon.Slice.class;
Field[] fields = clazzSlice.getDeclaredFields();

// 1
System.out.println("Number of fields: " + fields.length);

Even if we didn't explicitly declare any fields, notice that one field has been reported. Let's see whether it is synthetic and take a look at its name:

// true
System.out.println("Is synthetic: " + fields[0].isSynthetic());

// this$0
System.out.println("Name: " + fields[0].getName());
Similar to this example, we can check whether a method or a constructor is synthetic via the Method.isSynthetic() and Constructor.isSynthetic() methods.

Now, let's talk about bridge methods. These methods are also synthetic, and their goal is to handle the type-erasure of generics.

Consider the following Melon class:

public class Melon implements Comparator<Melon> {

@Override
public int compare(Melon m1, Melon m2) {
return Integer.compare(m1.getWeight(), m2.getWeight());
}
...
}

Here, we implement the Comparator interface and override the compare() method. Moreover, we explicitly specified that the compare() method takes two Melon instances. The compiler will proceed to perform type-erasure and create a new method that takes two objects, as follows:

public int compare(Object m1, Object m2) {
return compare((Melon) m1, (Melon) m2);
}

This method is known as a synthetic bridge method. We can't see it, but the Java Reflection API can:

Class<Melon> clazz = Melon.class;
Method[] methods = clazz.getDeclaredMethods();
Method compareBridge = Arrays.asList(methods).stream()
.filter(m -> m.isSynthetic() && m.isBridge())
.findFirst()
.orElseThrow();

// public int modern.challenge.Melon.compare(
// java.lang.Object, java.lang.Object)
System.out.println(compareBridge);
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.176.228