Java: private inner class synthesized constructors

This question already has an answer here:

  • Why is an anonymous inner class containing nothing generated from this code? 5 answers

  • If you write the code like,

    public class Outer {
          private class Inner {}
    }
    

    You will note that there is only one constructor private Outer$Inner(Outer)

    This constructor is required by Section 8.8.9 of the JLS, which says that if no constructor is defined a default constructor must be generated, and in this case the default constructor must be private,

    In a class type, if the class is declared public, then the default constructor is implicitly given the access modifier public (§6.6); if the class is declared protected, then the default constructor is implicitly given the access modifier protected (§6.6); if the class is declared private, then the default constructor is implicitly given the access modifier private (§6.6); otherwise, the default constructor has the default access implied by no access modifier.

    However, when you you instantiate an instance of Inner inside Outer with code like,

    public class Outer {
        private class Inner {}
            public String foo() {
                return new Inner().toString(); 
            }
    }
    

    The compiler has to generate a constructor that Outer can legally call (you can't legally call the private default constructor because it is private). So a new synthetic constructor must be generated by the compiler. The new constructor must be synthetic, according to section 13.1 of the JLS

    Any constructs introduced by the compiler that do not have a corresponding construct in the source code must be marked as synthetic, except for default constructors and the class initialization method.

    This second constructor has no corresponding construct in the source code, so this new constructor must be synthetic. The first private constructor must still be generated, since the JLS requires a private default constructor.


    This is not an answer, which I think has been well covered by sbridges. It is simply a working example that produces the behaviour you describe:

    public class Outer {
        private class Inner {
        }
    
        public static void main(String[] args) {
            printConstructors();
    
            //only one constructor is printed but two would appear if you 
            //uncommented the line below
    
            //new Outer().new Inner();
        }
    
        private static void printConstructors() {
            Constructor[] constructors = Outer.Inner.class.getDeclaredConstructors();
            for (Constructor c : constructors) {
                System.out.println(c.toGenericString());
            }
        }
    }
    

    The most likely answer is to respect what you declared in your source code. Doing this still allows to use the private constructor by reflection as you declared it.

    This also avoids to check whether the private constructor is actually called within the Inner class.

    链接地址: http://www.djcxy.com/p/91978.html

    上一篇: 为什么接口只能在最前面声明

    下一篇: Java:私有内部类合成构造函数