wood burning stoves 2.0*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Accessibility of private methods in inner classes Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Accessibility of private methods in inner classes" Watch "Accessibility of private methods in inner classes" New topic
Author

Accessibility of private methods in inner classes

john jain
Greenhorn

Joined: Sep 28, 2007
Posts: 6
Following is a slightly modified version of a question from the black belt factory.



I have 2 questions regarding above code:
1. How to run such code from command line? I tried java PrivateTest / Child / PrivateTest$Child but I always get an error (NoSuchMethodError: main). However, the code runs fine in Eclipse.
2. Can some explain the reasoning why the Parent's private method is visible inside Child class?
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9280
    
  17

Try the command java PrivateTest.Child. As for the visibility, Child class is a member of Parent class. Private members of a class are visible to other members of the class that's why Child class can access private methods of Parent class...


SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
Janeice DelVecchio
Saloon Keeper

Joined: Sep 14, 2009
Posts: 1613
    
  10

Why isn't p a member of the Child class, in which case, the output would be "Child."

The go() methods there aren't really overridden, because they have no visibility, right? You wouldn't be able to do this:



By the way, I can't get this to run either.
I tried "java PrivateTest.Child" -- I get NoClassDefFoundError


When you do things right, people won't be sure you've done anything at all.
john jain
Greenhorn

Joined: Sep 28, 2007
Posts: 6

Ankit, I tried to run using PrivateTest.Child also but no luck. Private members of a class are visible to other members of that class, but Child is not a member (it is a subclass) of Parent. Thus, the confusion.

Janeice, Did you try to compile using "super.go"? It also seems to compile fine.
Malte Wannerskog
Ranch Hand

Joined: Jan 06, 2011
Posts: 92

Janeice DelVecchio wrote:Why isn't p a member of the Child class, in which case, the output would be "Child."

The go() methods there aren't really overridden, because they have no visibility, right? You wouldn't be able to do this:





Compiles just fine...
However the output is still "parent" since


will invoke the go() method in parent.


OCPJP (310-065) - 88%
Janeice DelVecchio
Saloon Keeper

Joined: Sep 14, 2009
Posts: 1613
    
  10

So it compiles. But will it run?
Malte Wannerskog
Ranch Hand

Joined: Jan 06, 2011
Posts: 92

Janeice DelVecchio wrote:So it compiles. But will it run?


Edited my previous answer, it runs just fine, however the output is still "parent" since the go method of Child is not invoked.
If you however change the Child class as follows:



The output will be

Parent
Child

Edit: Also if you remove go() from Child it wont compile:




Frank Callahan
Greenhorn

Joined: Dec 30, 2010
Posts: 15
java PrivateTest$Child ought to work on the command line but doesn't, and "Exception in thread "main" java.lang.NoSuchMethodError: main" is what I get too. It does run in Eclipse though... In Thinking In Java, pp. 292-293, (1998 edition, the copy I have), Bruce Eckel suggests that main methods declared inside static inner classes can be a good way to include unit tests inside the source code of a top level class so that you can discard the static test class' .class file when you ship the code. He says that the correct command line syntax would be similar to what we've tried (java TestBed$Tester). So, it looks like there could be an actual practical use of the static inner class main method, although you'd probably want to use jUnit these days. Oddly, if you add a main method to the enclosing class, the command line will result in that main being run instead of the Child main, without NoSuchMethodError:



Compile command: javac -d classes src/misc/PrivateTest.java
Command line: java -cp classes misc.PrivateTest$Child
Output: In top main
java -version
java version "1.6.0_23"
Java(TM) SE Runtime Environment (build 1.6.0_23-b05)
Java HotSpot(TM) Server VM (build 19.0-b09, mixed mode)

I've set the same JDK as the default JRE in Eclipse, and there, the code runs as expected and prints Parent. I've been looking for an Eclipse feature that would generate a correct command line, but can't find one. This is frustrating for sure, but I don't think it will come up on the OCPJP exam when I take it this coming Monday. Hope so anyhow
Frank Callahan
Greenhorn

Joined: Dec 30, 2010
Posts: 15
Hi Malte,
Does it run from the command line, or in Eclipse or some other IDE? If on the command line, could you provide the details, including the java version and what you typed in?
Thanks!
Frank
Janeice DelVecchio
Saloon Keeper

Joined: Sep 14, 2009
Posts: 1613
    
  10

I guess I don't understand why the Child class can see the private method of the Parent class.
Malte Wannerskog
Ranch Hand

Joined: Jan 06, 2011
Posts: 92

Frank Callahan wrote:Hi Malte,
Does it run from the command line, or in Eclipse or some other IDE? If on the command line, could you provide the details, including the java version and what you typed in?
Thanks!
Frank


I can run it from both Eclipse and commandline.

I am running Win7. JDK 6.0.21

Compiled it with regular javac

javac PrivateTest.java

which resulted in the following files:

PrivateTest$1.class
PrivateTest$Child.class
PrivateTest$Parent.class
PrivateTest.class
PrivateTest.java

The command java PrivateTest$Child runs it and outputs "Parent"


Frank Callahan
Greenhorn

Joined: Dec 30, 2010
Posts: 15
Janeice,
Right, the real puzzle here is why the private instance method go() is visible through the Parent p reference declared in the Child main method. I understand that static methods can't be overridden so this might make sense if go was static (ignoring that it's private). Do all methods of static inner classes behave as if they are static? And why is the access modifier ignored? Very confusing.
Malte Wannerskog
Ranch Hand

Joined: Jan 06, 2011
Posts: 92

Frank Callahan wrote:Janeice,
Right, the real puzzle here is why the private instance method go() is visible through the Parent p reference declared in the Child main method. I understand that static methods can't be overridden so this might make sense if go was static (ignoring that it's private). Do all methods of static inner classes behave as if they are static? And why is the access modifier ignored? Very confusing.


I modified the code some. Removed the static modifier from the Parent class and made it public, also removed static modifier from Child. Also added final keyword to go() in parent to prove that go() is in not overidden in Child.


The code compiles and runs fine and outputs

Parent
Child

However, if Child was not an inner class of Parent then go() would not be visible and both the super.go() and p.go() would not compile (Oviously...)
Frank Callahan
Greenhorn

Joined: Dec 30, 2010
Posts: 15
Hi Malte,
Just tried on Windows XP, and it works both in Eclipse and on command line:

D:\projects\scjp>java -version
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)

D:\projects\scjp>java -cp bin PrivateTest$Child
Parent

Generally I work on an Ubuntu box, and that is where I can't get the code to run from the command line. So it looks like there is an issue with the 1.6.0_23-b05 JRE build for Linux, not some deeper issue that might show up on the exam.
Frank
Malte Wannerskog
Ranch Hand

Joined: Jan 06, 2011
Posts: 92

As Ankit mentioned at the beginning. The reason that Child can access the private method of Parent is because its a member of Parent
Frank Callahan
Greenhorn

Joined: Dec 30, 2010
Posts: 15
Maybe I have this one figured out... Here's some code that does not compile, that moves the Parent class outside PrivateTest:



The rule seems to be that any member of any nested class is visible to any other nested class within the same enclosing class.

Update - Makes sense now, as Ankit explained above. Thanks Malte!

Another Update - code as originally copied would not compile due to two public classes in a file. Fixed that.
Malte Wannerskog
Ranch Hand

Joined: Jan 06, 2011
Posts: 92

Frank Callahan wrote:Maybe I have this one figured out... Here's some code that does not compile, that moves the Parent class outside PrivateTest:



The rule seems to be that any member of any nested class is visible to any other nested class within the same enclosing class.


As previously mentioned this is the case.
Malte Wannerskog
Ranch Hand

Joined: Jan 06, 2011
Posts: 92

Frank Callahan wrote:
Update - Makes sense now, as Ankit explained above. Thanks Malte!


You're welcome. Was a pretty tricky question IMO. Appreciated since im preparing for the SCJP exam myself .
Frank Callahan
Greenhorn

Joined: Dec 30, 2010
Posts: 15
So. static inner classes are not just the same as top level classes. They have full access to all the members of the enclosing class.
Malte Wannerskog
Ranch Hand

Joined: Jan 06, 2011
Posts: 92

Frank Callahan wrote:So. static inner classes are not just the same as top level classes. They have full access to all the members of the enclosing class.


The key point here is not that the class is static but thats its an inner class.

Consider the following code:



The output will be

0
I am tested!

The inner class is a member of the outer class and therefore has complete access to the enclosing class.

By adding the static modifier to the inner class it will behave like a static method, not beeing able to access non-static content.

Update: Explanation above is not entirely correct since there is a difference between static nested classes and inner classes.
Frank Callahan
Greenhorn

Joined: Dec 30, 2010
Posts: 15
The K&B book's section on static nested classes describes them as follows:

"You’ll sometimes hear static nested classes referred to as static inner classes, but they really aren’t inner classes at all, by the standard definition of an inner class. While an inner class (regardless of the flavor) enjoys that special relationship with the outer class (or rather the instances of the two classes share a relationship), a static nested class does not. It is simply a non-inner (also called “top-level”) class scoped within another. " (p. 680)

To me, the visibility to static inner classes of other private nested classes declared inside the same outer class scope is a major distinction between regular "top-level" classes and static inner classes. Saying that they are not really inner classes seems wrong to me at this point, since they share the major advantage of non-static inner classes -- access to everything declared in the enclosing class regardless of access modifiers. Of course, the static inner class can't see instance variables directly, since it is static, but it can declare a reference to the outer class and access private members of the outer class that way, and can declare references to private classes declared inside the outer class and access their private members.

I don't know how useful static inner classes are in a practical sense, but they do seem to be full fledged inner classes.
Malte Wannerskog
Ranch Hand

Joined: Jan 06, 2011
Posts: 92

Frank Callahan wrote:The K&B book's section on static nested classes describes them as follows:

"You’ll sometimes hear static nested classes referred to as static inner classes, but they really aren’t inner classes at all, by the standard definition of an inner class. While an inner class (regardless of the flavor) enjoys that special relationship with the outer class (or rather the instances of the two classes share a relationship), a static nested class does not. It is simply a non-inner (also called “top-level”) class scoped within another. " (p. 680)

To me, the visibility to static inner classes of other private nested classes declared inside the same outer class scope is a major distinction between regular "top-level" classes and static inner classes. Saying that they are not really inner classes seems wrong to me at this point, since they share the major advantage of non-static inner classes -- access to everything declared in the enclosing class regardless of access modifiers. Of course, the static inner class can't see instance variables directly, since it is static, but it can declare a reference to the outer class and access private members of the outer class that way, and can declare references to private classes declared inside the outer class and access their private members.

I don't know how useful static inner classes are in a practical sense, but they do seem to be full fledged inner classes.


Good find. I guess my explanation earlier was somewhat incorrect. You should probably go with the K&B explanation of "static inner classes/static nested classes" .

As the quote says " It is simply a non-inner (also called "top-level") class scoped within another.".
Perhaps the correct explanation on the origial question (Why child can access private methods in Parent) is that Child is a static nested class and therefore is scoped withing Parent?

Update: Some information about nested classes
http://download.oracle.com/javase/tutorial/java/javaOO/nested.html
http://www.javaworld.com/javatips/jw-javatip106.html

Supports what you wrote earlier about using static nested classes for testing since the static nested class is beeing compiled into a separate class file. However JUnit or similar would probably be preferable.

"For example, if the supplemental code is only used for, say, debugging, then you only have to ship the Foo.class file and leave the Foo$Test.class file at home."

"Another interesting point to note is that static inner classes have, by definition, access to the outer class's protected and private fields. That is both a blessing and a curse since you can, in essence, violate the encapsulation of the outer class by mucking up the outer class's protected and private fields. Tread with care! "


So in fact, what you wrote earlier: "So. static inner classes are not just the same as top level classes. They have full access to all the members of the enclosing class." seems to be spot on (except that its a static nested class ;))

Note though that static nested classes cannot access non-static fields or methods of the enclosing class.
john jain
Greenhorn

Joined: Sep 28, 2007
Posts: 6

Thanks to you all for wonderful input. Learned quite a few things here. The meaning of how 'member' is interpreted is quite broad and it took a while to understand what Ankit may have meant in his post. Found some specs in JLS 3 to support your findings.

§8.1.6
A class body may contain declarations of members of the class, that is, fields (§8.3), classes (§8.5), interfaces (§8.5) and methods (§8.4). A class body may also contain instance initializers (§8.6), static initializers (§8.7), and declarations of constructors (§8.8) for the class. ... The scope of a declaration of a member m declared in or inherited by a class type C is the entire body of C, including any nested type declarations.


§6.6.1. says
...., otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.


I also had some luck running the program from command line. I think the issue occurred only for Mac \ Linux users who need to escape the dollar sign.
The command should be: java PrivateTest\$Child


Frank Callahan
Greenhorn

Joined: Dec 30, 2010
Posts: 15
Thanks to everyone who has participated in this thread for a very enjoyable and helpful learning experience. I'm taking the OCPJP 6 exam tomorrow afternoon, and being part of this exchange has gotten me psyched! Now I'm going to spend the rest of the morning doing the last of the 'Unlearned' Enthuware questions that I missed while taking the mock exams. Then tomorrow morning I'm going to review the APIs as a final prep for the test; I keep forgetting that String has no reverse() method...

Just to wrap up what this discussion has clarified about the access privileges of static inner classes, here's a sample program I put together:

The Outer Class, with a Non-Static and a Static Inner Class


Some code to exercise the above:


The Output:

One Outer Instance: I'm trying to hide, but can't hide from the inner non-static class!
Another Outer Instance: I'm trying to hide, but can't hide from the inner non-static class!
One Outer Instance: I'm trying to hide, but can't hide from the inner static class!
Another Outer Instance: I'm trying to hide, but can't hide from the inner static class!



 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Accessibility of private methods in inner classes
 
Similar Threads
Private Variables
init blocks example
One basic question
Overriding/overloading
question about polymorphism