Changing the declared access of a member or constructor to permit less access
may break compatibility with pre-existing binaries, causing a linkage error to be
thrown when these binaries are resolved. Less access is permitted if the access
modifier is changed from default access to private access; from protected
access to default or private access; or from public access to protected,
default, or private access. Changing a member or constructor to permit less
access is therefore not recommended for widely distributed classes.
Perhaps surprisingly, Java is defined so that changing a member or constructor to be more accessible does not cause a linkage error when a subclass (already) defines a method to have less access. So, for example, if the package points defines the class Point:
package points;
public class Point {
public int x, y;
protected void print() {
System.out.println("(" + x + "," + y + ")");
}
}
class Test extends points.Point {
protected void print() { System.out.println("Test"); }
public static void main(String[] args) {
Test t = new Test();
t.print();
}
}
then these classes compile and Test executes to produce the output:
Test
If the method print in class Point is changed to be public, and then only the
Point class is recompiled, and then executed with the previously existing binary
for Test then no linkage error occurs, even though it is improper, at compile time,
for a public method to be overridden by a protected method (as shown by the
fact that the class Test could not be recompiled using this new Point class unless
print were changed to be public.)
Allowing superclasses to change protected methods to be public without breaking binaries of preexisting subclasses helps make Java binaries less fragile. The alternative, where such a change would cause a linkage error, would create additional binary incompatibilities with no apparent benefit.