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.