• Post Reply Bookmark Topic Watch Topic
  • New Topic

Found Something Quirky: No Default Constructor in Inner Classes in Another Package?  RSS feed

 
Perry Terrance
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One misconception that I already know about is that most people think that Java Classes with no user-defined constructor automatically create a default no-arg constructor for all classes. That statement is false.

The scenario in which this happens is in a non-static Inner Class.

For example:



Suppose I extend outerClass to another class within the same package



This doMethod code works perfectly. From what I read, transparently the Java Compiler passes the outerClass reference to a single-argument constructor of the innerClass.

The Quirky Thing though however - if I do the same exact code but put it into another package:


The innerClass constructor can't be invoked like this...

Why is that?

 
Hunter McMillen
Ranch Hand
Posts: 492
Firefox Browser Linux VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have a look at this page from the Java tutorials about visibility and access specifiers: http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

The answer you are looking for it near the bottom

Hunter
 
Perry Terrance
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hunter McMillen wrote:Have a look at this page from the Java tutorials about visibility and access modifiers: http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

The answer you are looking for it near the bottom

Hunter


I think my question is going beyond the basics of visibility/access modifiers.

My InnerClass is Protected - therefore it should be able to accessed by the subclasses of OuterClass even if it in another package (com.mypackage2).

However - why is it I cannot access the transparent constructor, but the same exact construction logic in com.mypackage1 can?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Perry Terrance wrote:
My InnerClass is Protected - therefore it should be able to accessed by the subclasses of OuterClass even if it in another package (com.mypackage2).


And it is accessible. It's just the constructor that's not, because the c'tor is protected, and hence accessible only to subclasses of innerClass and classes in its package. I confirmed this with javap. I created a top-level package-private class, and its generated constructor was package-private, also confirmed with javap.



I haven't bothered to dig up the relevant part of the JLS, but it looks like compiler-generated c'tors have the same access level as their defining class.
 
Perry Terrance
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah - this is fascinating!

So what I'm guessing is happening is this:

By specifying the innerClass as Protected, the Default Constructor for innerClass is automatically set to Protected as well.

At the OuterClass member level, the Protected innerClass itself CAN be accessed by outerClass-subclasses in BOTH com.mypackage1 and com.mypackage2.

However, the Protected Constructor of innerClass itself is one-single layer below, so it can only be access by classes in the SAME com.mypackage1, NOT by com.mypackage2.

Did I get that right?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Perry Terrance wrote:Ah - this is fascinating!

So what I'm guessing is happening is this:

By specifying the innerClass as Protected, the Default Constructor for innerClass is automatically set to Protected as well.

At the OuterClass member level, the Protected innerClass itself CAN be accessed by outerClass-subclasses in BOTH com.mypackage1 and com.mypackage2.

However, the Protected Constructor of innerClass itself is one-single layer below, so it can only be access by classes in the SAME com.mypackage1, NOT by com.mypackage2.

Did I get that right?


Yup.

Except that you didn't mention that the protected c'tor of innerClass can also be accessed by subclasses of innerClass.

EDIT: Actually, I would rephrase this whole part:
the Protected Constructor of innerClass itself is one-single layer below, so it can only be access by classes in the SAME com.mypackage1,


as simply, "The c'tor of innerClass is protected, and therefore only accessible to subclasses of innerClass and classes in the same package as innerClass."
 
Perry Terrance
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Couldn't have said it better myself

and to subclass innerClass - you will have to create a new class that extends outerClass and then within it create another "inner class" that extends innerClass.

My brain is melting...
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Perry Terrance wrote:
and to subclass innerClass - you will have to create a new class that extends outerClass and then within it create another "inner class" that extends innerClass.


Well, you could add a subclass of innerClass as another inner class of outerClass.





Or you could do something like this:


My brain is melting...


Yeah, mine too. Thanks for that.
 
Perry Terrance
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also - I wonder about this - shouldn't this work as well?




Since AnotherInnerClass is a subclass of innerClass now, the Protected Constructor of innerClass should be accessible for all codes inside AnotherInnerClass right? However, in my Eclipse it keeps giving me a red-mark saying the innerClass constructor is not visible (which doesn't make sense....)
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Perry Terrance wrote:Also - I wonder about this - shouldn't this work as well?




Since AnotherInnerClass is a subclass of innerClass now, the Protected Constructor of innerClass should be accessible for all codes inside AnotherInnerClass right? However, in my Eclipse it keeps giving me a red-mark saying the innerClass constructor is not visible (which doesn't make sense....)


I think you'd get the same thing even if these weren't inner classes. Roughly speaking, the "accessible from subclass" bit of the protected access rule also includes "...but only through this. or super.".

I haven't tried to compile the below, but I think the results will be as indicated.

 
Perry Terrance
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jeff Verdegan wrote:
I think you'd get the same thing even if these weren't inner classes. Roughly speaking, the "accessible from subclass" bit of the protected access rule also includes "...but only through this. or super.".


Interesting - this is first time I ever heard of this unique constraint of the Java language. And frankly - I find it kind of odd this constraint doesn't happen when all the code in the same package - ergo:

 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Perry Terrance wrote:
Jeff Verdegan wrote:
I think you'd get the same thing even if these weren't inner classes. Roughly speaking, the "accessible from subclass" bit of the protected access rule also includes "...but only through this. or super.".


Interesting - this is first time I ever heard of this unique constraint of the Java language.


I think that the usual way people access protected methods is through super or this anyway, so it often doesn't come up, or doesn't come up until later in one's Java career.

And frankly - I find it kind of odd this constraint doesn't happen when all the code in the same package - ergo:


Because protected means "accessible by subclasses and classes in the same package," and the "in the same package" part doesn't care about accessing through super or this. That's only relevant when accessing via a subclass.

 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!