5

Given this little pice of code:

import java.util.Arrays;

public class Sample {
    private final int test;

    private Sample(int test) {
        this.test = test;
    }

    public static void main(String[] args) {
        System.out.println(Arrays.toString(Hello.class.getDeclaredConstructors()));
    }

    public static class Hello {
        private final int i;

        private Hello(int i) {
            this.i = i;
        }

        public int getI() {
            return i;
        }

        public static class Builder {
            private int i;

            private Builder() {

            }

            public static Builder builder() {
                return new Builder();
            }

            public void add(int i) {
                this.i = i;
            }

            public Hello build() {
                return new Hello(i);
            }
        }
    }
}

i don't understand the output that is shown:

[private Sample$Hello(int), Sample$Hello(int,Sample$1)]

what is the second listed constructor in here with the second parameter to the Builder. I thought that the output will only show the private constructor of Hello but not the second one.

BigMichi1
  • 307
  • 1
  • 11

1 Answers1

4

Builder is a static nested class of Hello, therefore it should be able to access private constructor Sample$Hello(int).

However, JVM doesn't have any special support for nested classes, therefore, from the JVM point of view, Builder cannot access Sample$Hello(int).

In order to solve this problem compiler generates synthetic constructor Sample$Hello(int,Sample$1) with default visibility, and calls it instead of Sample$Hello(int) from Builder.

Sample$1 is an empty class generated by the compiler to make distinguished signature for Sample$Hello(int,Sample$1). Actually, the second argument of this constructor is always null.

axtavt
  • 239,438
  • 41
  • 511
  • 482
  • 2
    Makes sense - would like a reference to back your suggestion though. – OldCurmudgeon Mar 10 '14 at 09:58
  • I cannot find any official proof so far, but you can verify this behavior by doing `javap -c -private Sample$Hello` and `javap -c -private Sample$Hello$Builder`. Also, synthetic constructor disappears if you comment out `new Hello()` in `Builder` or make constuctor of `Hello` `public`. – axtavt Mar 10 '14 at 12:12