Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reflection returns two constructors when accessing it's private constructor from an inner class

public class Base {

    private Base instance;

    private Base() {
    }

    public static class BaseHelper {
        Base instance = new Base();
    }
}

In above example I have one no-argument constructor in base class. Now I'm listing the constructors of this class like this:

Constructor<?>[] constructors = Base.class.getDeclaredConstructors();
System.out.println(constructors);

When running this code I get the following output:

[private com.Base(), com.Base(com.Base)]

This tells me that there are two constructors:

  • a private constructor that I have declared
  • a public default constructor

Why is this?

like image 408
Amit Avatar asked Feb 12 '23 05:02

Amit


1 Answers

The compiler creates two constructors, because your BaseHelper class accesses the private constructor of your Base class.

When compiled, the inner class is "extracted" from the containing class. If the class BaseHelper was outside the Base class it could not access the private constructor - that's why the compiler creates a synthetic constructor. This is the second constructor that you see.

Synthetic is a field modifier and in essence means compiler-generated.

package de.test;

import java.lang.reflect.Constructor;

public class Base {

    private Base instance;

    private Base() {
    }

    public static class BaseHelper {
        Base instance = new Base();
    }

    public static void main(String[] args) {
        Constructor[] constructors = Base.class.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor + " - synthetic? " + constructor.isSynthetic());
        }
    }
}
like image 85
maxdev Avatar answered Feb 13 '23 19:02

maxdev