Re: Confirm bad news
- From: Kevin McMurtrie <kevinmcm@xxxxxxxxx>
- Date: Tue, 30 Jun 2009 22:16:40 -0700
In article <--SdnevlI8ycE9fXnZ2dnUVZ_gSdnZ2d@xxxxxxxxxxxxx>,
"Scott A. Hightower" <VastError@xxxxxxxxxxxxxxx> wrote:
I want to prevent direct access to fields of one nested class from another
nested class within the same enclosing class. It appears that this is not
possible, but before giving up I thought I'd see if someone can point out
something I've overlooked.
It has long bothered me that the private modifer is completely ignored for
intra-class accesses. For example:
class Outer {
class A {...}
class B {private int secret;}
}
A method of inner class A can freely access B.secret, so long as it has a
reference to an instance of B.
The language reference seems to confirm this, stating that (paraphrased) all
members (and members of members, etc.) have scope throughout the compilation
unit. More specifically, from "6.6.1 Determining Accessibility":
"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
... that encloses the declaration of the member or constructor."
Even if class A above is static, it just needs a reference to an instance of
B. I learned this by experiment.
Until now, I've just accepted this, and told myself that there is no need to
encapsulate nested classes because they are usually simple and express
simple concepts. In those rare cases where I wanted to prevent direct
modification, I could make the field a blank final and require creating a
new instance of the nested class, with whatever special logic was required
contained in the sole constructor.
But I've run into a case where I wish to avoid the overhead of creating a
new instance unless absolutely necessary. Sometimes it is safe to directly
modify the value and sometimes a new instance is called for. Therefore, a
blank final cannot be used. But, as soon as the final modifer is removed, I
have opened the door for some future maintainer (even myself) in too much of
a hurry to understand why a new value cannot just be assigned directly.
At this point my choices seem to be comments that warn against direct
modification, or enforcing the encapsulation by moving the nested class into
its own compilation unit. The latter is foolproof, but it seems a shame
because until now the class has been a self-contained standalone utility.
The news is true, in a way. It's definitely not allowed in bytecode.
The source compiler is adding hidden methods to access private fields.
It's assumed that subclasses are friendly to each other. For Java 1.5
onwards, you can break this friendliness by moving the declarations so
they're in the same file but not in a common parent class. This forces
them to be static classes and it stops making accessor methods for them.
class MainClass {
...
}
class A
{
B b;
void foo() {b.secret++;} //Won't compile
}
class B {private int secret;}
I recall that Java 1.4 considers everything in one file to be friendly.
--
I will not see your reply if you use Google.
.
- Follow-Ups:
- Re: Overly friendly nested classes (was Confirm bad news)
- From: Scott A. Hightower
- Re: Overly friendly nested classes (was Confirm bad news)
- References:
- Confirm bad news
- From: Scott A. Hightower
- Confirm bad news
- Prev by Date: Re: ArrayList.Iterator.remove()
- Next by Date: Re: JDK1.6 won't compile my JDK1.5 code
- Previous by thread: Confirm bad news
- Next by thread: Re: Overly friendly nested classes (was Confirm bad news)
- Index(es):
Relevant Pages
|