7

Let's assume we have a class:

public class SomeClass {    
    protected SomeClass () { 
    }
}

In MainClass located in different package I tried to execute two lines:

public static void main(String[] args) {
    SomeClass sac1 = new SomeClass(); 
    SomeClass sac2 = new SomeClass() {}; 
}

Because of protected constructor, in both cases I was expecting program to fail. To my suprise, anonymous initialization worked fine. Could somebody explain me why second method of initialization is ok?

Tinki
  • 1,486
  • 1
  • 21
  • 32

4 Answers4

11

Your anonymous class

SomeClass sac2 = new SomeClass() {}; 

basically becomes

public class Anonymous extends SomeClass {
    Anonymous () {
        super();
    }
}

The constructor has no access modifier, so you can invoke it without problem from within the same package. You can also invoke super() because the protected parent constructor is accessible from a subclass constructor.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • To my great surprise, the same thing happens when you use a constructor which does have arguments. In this case I think your explanation no longer stands. – Andrei Jul 07 '17 at 08:50
  • @Andrei I didn't mention parameters/arguments. They play no role in the accessibility check. – Sotirios Delimanolis Jul 07 '17 at 15:30
  • Not in the accesibility check, no. But if you have a class with only a protected constructor WITH params, you have to explicitly invoke its constructor with params, from the child. I was saying that this rule seems to be skipped for anonymous classes. – Andrei Jul 07 '17 at 16:32
  • @Andrei What you're saying is correct, but doesn't seem relevant here. The OP's question was about the accessibility of a constructor from an anonymous class in a different package. – Sotirios Delimanolis Jul 07 '17 at 16:51
4

Those two little braces in

SomeClass sac2 = new SomeClass() {};

invoke a lot of automatic behavior in Java. Here's what happens when that line is executed:

  1. An anonymous subclass of SomeClass is created.
  2. That anonymous subclass is given a default no-argument constructor, just like any other Java class that is declared without a no-argument constructor.
  3. The default no-argument constructor is defined with visibility public
  4. The default no-argument constructor is defined to call super() (which is what no-arg constructors always do first).
  5. The new command calls the no-argument constructor of this anonymous subclass and assigns the result to sac2.

The default no-argument constructor in the anonymous subclass of SomeClass has access to the protected constructor of SomeClass because the anonymous subclass is a descendant of SomeClass, so the call to super() is valid. The new statement calls this default no-argument constructor, which has public visibility.

Edward
  • 5,942
  • 4
  • 38
  • 55
3

The first line fails, because SomeClass's constructor is protected and MainClass is not in SomeClass's package, and it isn't subclassing MainClass.

The second line succeeds because it is creating an anonymous subclass of SomeClass. This anonymous inner class subclasses SomeClass, so it has access to SomeClass's protected constructor. The default constructor for this anonymous inner class implicitly calls this superclass constructor.

rgettman
  • 176,041
  • 30
  • 275
  • 357
0

Your line

SomeClass sac2 = new SomeClass() {};

creates an instance of a new class which extends SomeClass. Since SomeClass defines a protected constructor without arguments, a child class may call this implicitly in its own constructor which is happening in this line.

Ray
  • 3,084
  • 2
  • 19
  • 27