Let's start with another behavior: even if you declare a method/variable as private, another instance of the same class can access it. That's OK I can live with it. I call these class-private and not instance-private.
Now the question part:
For example, at runtime I want to be able to check that all String variables in this
class are not null, and if they are null they should be changed to the string "NULL".
I can run through the variables using reflection and get their values. But if I extend my class and add private or even protected variables my base class can't access them. I have to setAccessible
on the variables before I can use them.
So please explain to me why the base-class (super-class) can't access private/protected variables from its sub-class. It is its sub-class, so I don't get it. What's the idea behind this?
I know that the super-class should not know about its sub-classes, but in my example it makes sense, no?
Is it because I can't or shouldn't restrict my sub-classes in this way?
Update:
Based on the answers, I want to know also: Why isn't accessing another instance's private variables from the same class considered a violation of encapsulation?
It's as simple as it's a violation of encapsulation. Another class should not be able to reach into your class and be messing around with things, even if you generalize that class. How does a Vehicle know anything about a Car for example? The whole point of a base class is to provide for the sub-classes, but like an over-protective parent, what you're suggesting would be too much.
To answer your update question (as the original question is well answered already) the purpose of private is to hide implementation details so that those implementation details don't become dependencies. This is the essence of object oriented programing - encapsulation ensuring that complexity is kept manageable by keeping different parts isolated to their own area.
Since the class knows about its own implementation - it defines it, there is nothing gained in limiting access to other instances, since the class implementation declares all the private instances it is already exposed to all of these details.
Hiding it in this case would in fact increase complexity as you would have to add an additional access level to allow class-level visibility instead of instance level visibility without actually really encapsulating any further complexity.
It's all about inheritance and encapsulation.
Java's visibility rules state that
- private members can only be accessed in the class that defines them
- protected members can only be access in
- the class that defines them
- subclasses of the class that defines them
- other classes in the same package as the class that defines them
Of course, as you mention, in reflection you can change the rules (unless a SecurityManager forbids it)
I tend to look it more from a pragmatic and realistic standpoint:
public class Test1 {
private int a = 1;
public static void main(String s[]) {
System.out.println((new Test1()).a);
System.out.println((new Test1()).getA());
System.out.println((new Test2()).getA());
}
public int getA() { return a; }
}
class Test2 extends Test {
private int a = 2;
public int getA() { return a; }
}
What syntax would you propose Test1
use to access private member a
in Test2
. When Test1
is written, Test2
may not even exist.
As well, a base-class (super-class) doesn't know when it has been inherited from. To allow a base-class to know when it has been inherited, you would have to be able to modify the base-class when inheriting from it. Are you suggesting that I should somehow modify my local copy of ArrayList
when I write:
class MyArrayList extends ArrayList
And what happens the day I decide to run my code on your computer, do you get my modified copy of ArrayList
that knows about MyArrayList
, or do I modify the copy on your computer somehow?
Could these issues be overcome somehow? Certainly. Is there any value in allowing it? None that I can see.