Home » Java » reflection – Why does the java compiler create a synthetic constructor in outer class?-Exceptionshub

reflection – Why does the java compiler create a synthetic constructor in outer class?-Exceptionshub

Posted by: admin February 25, 2020 Leave a comment

Questions:

I can’t understand oracle java tutorial that writes:

public class SyntheticConstructor {
    private SyntheticConstructor() {}
    class Inner {
    // Compiler will generate a synthetic constructor since
    // SyntheticConstructor() is private.
    Inner() { new SyntheticConstructor(); }
    }
}

Since the inner class’s constructor references the private constructor of the enclosing class, the compiler must generate a package-private constructor of the enclosing class(that is SyntheticConstructor here).

So why does the java compiler have to create the synthetic constructor in the outer class SyntheticConstructor?

How to&Answers:

This is caused by a discrepancy between the access rules of the Java language and the access rules of the JVM.

The JVM doesn’t have the concept of inner classes, that is entirely a made-up construct invented by the Java compiler. The compiled code of that source file is 2 independent classes.

When the source code is:

public class SyntheticConstructor {
    private SyntheticConstructor() {}
    class Inner {
       Inner() { new SyntheticConstructor(); }
    }
}

The compiler generates .class files equivalent to the following source code (from javap disassembled byte code):

public class SyntheticConstructor extends Object {
    private SyntheticConstructor() {
        super();
        return;
    }
}

class SyntheticConstructor$Inner extends Object {
    final SyntheticConstructor this$0;

    SyntheticConstructor$Inner(SyntheticConstructor outer) {
        this.this$0 = outer;
        super();
        new SyntheticConstructor();
        return;
    }
}

In that code, the new SyntheticConstructor() expression is trying to invoke the private constructor of another class. Since that is not allowed by the JVM, the compiler must create a hidden synthetic non-private constructor that it can call instead.

This is true whenever code in an outer/inner/nested class accesses a private member of another outer/inner/nested class of the same top-level class.