In the following example, x
can be changed by class B
even though it's a private member of class A
. What's the reason for this?
import java.util.Date;
class A {
private Date x;
public A(){
super();
x = new Date();
}
public Date getDate(){
return x;
}
public void print(){
System.out.println(this.x);
}
}
class B {
public static void main(String[] args){
A a = new A();
a.print();
Date d = a.getDate();
d.setMonth(12);
System.out.println(d);
a.print();
}
}
The output is:
Initial date generated by A
Date changed by B
Date changed by B (why does it change a private member here?)
答案 0 :(得分:6)
private
prevents a variable from being accessed directly by another class. You cannot write d.x
to read or write to x
.
If the class chooses to return a reference to x
via a public method, though, that's it's own choice to pierce the veil of privacy. Nothing stops A
from allowing x
to be read from a getter or modified from a setter.
In recent years the Java community has recognized the problem with this: namely, if you return a reference to a private mutable object, you open the door for your class's internal state to be mucked with without its knowledge. To protect against this, it has become good practice to make classes immutable whenever possible.
Indeed, Date
is a perfect example of a poorly-designed mutable class. The java.time
package introduced in Java 8 added a slew of immutable time and date classes to replace Date
. You can now return a private Instant
and not worry about callers being able to change it.
It's important to point out that immutability comes from how a class is defined. It's not a language-level feature like private
. Confusingly, final
can be used to make variables immutable, but applying it to a class does not make the class immutable (it makes it unextendable).
答案 1 :(得分:3)
You're not changing the private property. Try this and see it fail:
A a = new A();
a.x = someOtherValue;
But the A
class does allow you to read the property:
public Date getDate(){
return x;
}
And the Date
class allows you to set its property:
d.setMonth(12);
No private
member is being accessed outside of a class here. Date
and A
are two different classes.
答案 2 :(得分:1)
This did not change x
it is still pointing to the same object. What was changed is the object itself.
答案 3 :(得分:0)
You are confusing reference with value.
The Date
object referred to by x
never changes and the field x
is inaccessible from the sub class - ie the sub class can't assign a different Date
object to x
.
However, the getter allows you to access the object referred to by x
, and (perhaps unexpectedly) Date
objects are mutable - that is a Date
's value can be changed. It's still the same Date
object, but the instant in time it represents is different.
IMHO, the Date
class is "broken"; it should be immutable.
答案 4 :(得分:0)
The getDate()
method is public. The getter method is public, that is you can now access the object and change its value. Date d
and Date x
are only reference to those objects not the actual objects.