Default and Protected - 2020
Both protected and default access levels are tied to packages. A class with default access has no modifier preceding it in the declaration. Default access is simple in that only the code within the same package can access code with default access. In other words, a class with default access can be seen only by classes within the same package. For instance, if class A and class B are in different package, and class A has default access, class B won't be able to create an instance of class A or declare a variable or return type of class A. In fact, class B has to pretend that class A doesn't even exist. We simply can't type it into our code at all. If we do, the compiler will complain.
Let's take a look at the following file:
package packageA; class classA {}
And another file:
package packageB; import packageA.classA; class classB extends classA {}
Then, we get the error from classB file:
The type packageA.classA is not visible. classA can not be resolved to a type.
Let's think about the implications.
A default class with public methods means the public methods aren't really public at all. We can't access a method if we can't see the class.
Why would anyone want to restrict access to code within the same package?
In most of the cases, packages are designed as a group of classes that work together as a related set. So it might make sense that classes within the same package need to access one another's code, while as a package, only a small number of classes and methods are exposed to the outside the package.
Protected access is almost identical to default access. But with one critical exception. Protected access allows subclasses to inherit the protected members even if those subclasses are outside the package of the superclass they extend. In other words, a default member may be accessed only if the class accessing the member belongs to the same package, whereas a protected member can be accessed (through inheritance) by a subclass even if the subclass is in a different package.
Let's take a look at the following two classes:
package packageA; public class AClass { // default access void test() { System.out.println("classA"); } }
Another file:
package packageB; import packageA.AClass; class BClass { public static void main(String[] args) { AClass ac = new AClass(); ac.test(); } }
The test() method in the first file has default access. And the class AClass is in a different package from the BClass which is trying to access the method in AClass.
It failed. BClass is not in the same package as AClass. So BClass can't see AClass.
Default and protected behavior differ only when we talk about subclasses. If the protected keyword is used to define a member, any subclass of the class declaring the member can access it through inheritance.
It doesn't matter if the superclass and subclass are in different packages, the protected superclass member is still visible to the subclass. This is in contrast to the default behavior, which doesn't allow a subclass to access a superclass member unless the subclass is in the same package as the superclass.
So, when you think of default access, think package restriction. But when you think protected, think package + kids.
Let's take a look at a protected instance variable of a superclass.
package packageA; public class Parent { protected int x = 10; }
Another source:
package packageB; import packageA.Parent; class Child extends Parent { public void test() { System.out.println(" x = " + x); } }
The Child class is accessing the protected variable through inheritance. Notice, though, any time we talk about a subclass having access to a superclass member, we could be talking about the subclass inheriting the member, not simply accessing the member through a reference to an instance of the subclass.
Watch what happens if the subclass Child tries to access a protected variable using a Parent class reference.
First source is the same as previous example:
package packageA; public class Parent { protected int x = 10; }
The differences are in this second file:
package packageB; import packageA.Parent; class Child extends Parent { public void test() { System.out.println(" x = " + x); Parent p = new Parent(); System.out.println(" x in parent = " + p.x); } }
The compiler complains:
C:\ProtectedTest\src>javac -d . packageB/Child.java packageB\Child.java:8: x has protected access in packageA.Parent System.out.println(" x in parent = " + p.x); ^ 1 error
The complain shows that subclasses outside the package can't use a superclass reference to access a protected member.
For a subclass outside the package, the protected member can be accessed only through inheritance.
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization