private static MyInnerClass extends OtherClass + protected methods
Hi!
Consider this case:
publicclass A{
privatestaticclass A1extends B{
// this would resolve the error:
// protected static void b() { B.b(); }
}
void a(){ A1.b();}// ERROR: B.b() is inaccessible
}
publicclass B{
protectedstaticvoid b(){}
}
(Where A and B are in different packages.)
Why is B.b() inaccessible here?
A1 extends B, so it sees its protected methods.
A is a nesting class of A1, so it sees the protected methods of A1.
What am I missing here?
Thank you!
Agoston
When you inherits protected method of another class it becames private in child, and you can't access it from any class except child class.
Don't people test things any more? This entire thread seems to be absolute nonsense. The example compiles and runs in its original form (i.e. without the A1.b() method). It does not get 'error B.b() is inaccessible'. JDK 1.5.0_06. What compiler were you using?
Reply #1 is absolute nonsense. A protected member is accessible to all subclasses and classes in the same package. It does not 'become private in child'.
Please.
ejpa at 2007-7-13 23:49:37 >

Here's my test:
> javac A.java
A.java:17: b() has protected access in b.B
void a() { A1.b(); } // ERROR: B.b() is inaccessible
^
1 error
> java -version
java version "1.4.2_05"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_05-b04)
Java HotSpot(TM) Client VM (build 1.4.2_05-b04, mixed mode)
(B was in package b, A was in package a, by the way.)
I interpret your answer then as "this is a bug in java 1.4.2, but has been fixed in java 1.5".
Do you agree?
As far as I can see the error message is perfectly valid, since the access you're attempting is neither in a subclass of B, nor in the same package.
It doesn't have private access in A1, it has protected access which, in this case, is slightly more restrictive.
A and A1 are co-habitting, and have access to one anothers private parts, but one doesn't have access to one's ancestor's private parts.
Just checked the code on 1.5. The error is as OP said.
Message was edited by:
malcolmmc
Hm... I still don't get it.
A1 extends B, therefore what's protected in B is also protected in A1. E.g. a child of A1 sees that protected b() in B even if it's not in the same package as B. (I've tried it out.)
In other words: if A has some protected methods, it shouldn't make a difference whether they are inherited or defined in A1 itself.
Still, if the protected b() is directly defined in A1, it's visible from the nesting class (as it should be), but if b() is only inherited, it's not.
I consider this behavior highly inconsistent.
Agoston
Some other minor things:
You wrote:
"It doesn't have private access in A1, it has protected access which, in this case, is slightly more restrictive."
How is protected access more restrictive than private? I've been pretty sure it's the other way round.
"A and A1 are co-habitting, and have access to one anothers private parts, but one doesn't have access to one's ancestor's private parts."
But B.b() is not private in B, it's protected.
>Reply #1 is absolute nonsense. A protected member is accessible to all subclasses and classes in the same package. It does not 'become private in child'.
From Declaration and Access control section of Java Certified Programmers exam: "Once the subclass-outside-the-package inherits the protected member, that
member (as inherited by the subclass) becomes private to any code outside the
subclass. So if class Neighbor instantiates a Child object, then even if class Neighbor
is in the same package as class Child, class Neighbor won抰 have access to the Child抯
inherited (but protected) variable x. The bottom line: when a
subclass-outside-the-package inherits a protected member, the member is essentially
private inside the subclass, such that only the subclass?own code can access it."
It seems nobody catch A1 and B are in different packages, if modifiers are not changed to private in the case it results any class can access any protected method in any package just after one additional step - inheratnce, such way make protected modifier useless.
As for workaround - defining the same name method which call "super" method it seems ok but new method isn't override parent method because static methods can't be overriden, you just define new method with the same name.
OK, my mistake, I missed the part about different packages.
However the following further inner class of A compiles for me:
private static class A2 extends A1
{
A2()
{
b();
A1.b();
}
}
using the OP's original code without A1.b().
The statement quoted from the JCP exam is not correct. The inherited protected member is available to subclasses of A1, so the protected member b() doesn't 'become private' at all. It stays as is was, i.e. protected, i.e. accessible within the original package or to subclasses.
Nothing changes.
ejpa at 2007-7-13 23:49:37 >

Yes, methods doesn't become private in parent class, but tey are private in child class(if classes reside in different packages) and of cause private members of subclass is available in the subclass :)
Hi ejp,
Sorry, but you are right, it seems better to say methods remains protected and vitually remains in parent package, this way no one from child package can access the methods but they are accessible from parent package.
But in your sample it doent't mater say private or say protected+old package.
> How is protected access more restrictive than> private? I've been pretty sure it's the other way> round.> Because classes in the same source file can access one another's privates. But, as seen here, not fields that are inherited.
> OK, my mistake, I missed the part about different
> packages.
>
> However the following further inner class of A
> compiles for me:
>
> private static class A2 extends A1
> {
> A2()
> {
> b();
> A1.b();
> }
> }
>
> using the OP's original code without A1.b().
That's what I was talking about: b() can be called from children, but not from the nesting class.
>
> The statement quoted from the JCP exam is not
> correct. The inherited protected member is available
> to subclasses of A1, so the protected member
> b() doesn't 'become private' at all. It stays as is
> was, i.e. protected, i.e. accessible within the
> original package or to subclasses.
If it stays protected, why can't the nesting class see it? (Once again, a protected method defined in A1 and not inherited from B _is_ visible from A.)
It seems as if the inherited protected method teleports into some mysterious realm of visibility levels between private and protected. (I.e. it's like protected, only from a nesting class it's seen as super-private - since the nesting class should even be able to see the private methods of its inner class, shouldn't it?)
This whole inconsequent behavior on the part of the compiler feels like a huge bug to me.
> Nothing changes.
Unfortunately. :)
Agoston
Hi AgostonBejo,
As I said visibility is protected but method in child class still belongs to parent package, so you can't see the method from any classes except child or classes from parent package.
Try to create one more class in "parent" package, you'll be able to invoke protected method in child class (I've tried with 1.5._06)
> Because classes in the same source file can access
> one another's privates.
No, they can't. Both of the folowing classes are in the same source file. I get "not accessible" compiler errors on both i1 lines. (Note that in this particular case if it compiled and we tried to run it, we'd get infinite recursion. I just threw this together as a very simple counterexample to the above statement.)
public class AAA {
private int i1 = new BBB().i1;
}
class BBB {
private int i1 = new AAA().i1;
}
> If it stays protected, why can't the nesting class
> see it? (Once again, a protected method defined in A1
> and not inherited from B _is_ visible from A.)
>
> It seems as if the inherited protected method
> teleports into some mysterious realm of visibility
> levels between private and protected. (I.e. it's like
> protected, only from a nesting class it's seen as
> super-private - since the nesting class should even
> be able to see the private methods of its inner
> class, shouldn't it?)
Sorry, I'm a bit lost. I'm not good at putting together code samples and their deltas from different posts. Can you post the specific code sample along with your question, so it's all together in one place? Thanks.
> When you inherits protected method of another class
> it becames private in child, and you can't access it
> from any class except child class.
if you take a look at the JLS, it says:
A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.
I get from this that you cannot access a protected member outside of its package except from a DESENDENT class (i.e. a child class or a child or a child class, etc).
I haven't actually tried it today, but that's what I get from what it says in the spec.
> > When you inherits protected method of another
> class
> > it becames private in child, and you can't access
> it
> > from any class except child class.
>
> if you take a look at the JLS, it says:
>
> A protected member or constructor of an object may be
> accessed from outside the package in which it is
> declared only by code that is responsible for the
> implementation of that object.
>
> I get from this that you cannot access a protected
> member outside of its package except from a DESENDENT
> class (i.e. a child class or a child or a child
> class, etc).
>
> I haven't actually tried it today, but that's what I
> get from what it says in the spec.
btw, since your outer class (class A) is not responsible for the implementation of an object of A1, it does not have access to that method, although A1 would have.
> > Because classes in the same source file can access
> > one another's privates.
>
> No, they can't.
since jverd didn't explain where the error in that statement was, I will.
from the JLS:
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 that encloses the declaration of the member or constructor.
hence, it's not a question of being in the same file, its a question of being contained in the same top level class.
hence if you choose to have multiple non-nested classes within a single file, they don't share access to each others private fields and methods.
- Adam
OK, now I finally got it. So a protected method of a nesting class is visible for its nesting class not because the nesting class sees ALL the methods of the nested class, but because they are in the same package.
This, by the way breaks the rule of private < package < protected < public, since there are occasions when a class can see the private methods of another one, but not all of its protected ones. (Namely the one in the example.)
Personally I don't think protected members should be visible at the package level, but it's a bit late to change that now.