You might recall that an access modifier describes who can use your code. Java has four different access modifiers:
private: only accessible within the class itself;default: accessible to classes from the same package, also known as package-private;protected: accessible to classes from the same package and any extending classes.public: can be accessed from anywhere;
You're already aware of most of these, but one of the most intriguing ones remains: the protected access modifier. Let's place it among the modifiers you're already familiar with:
This modifier states that only subclasses and any classes within the same package can use a class member. You can't protect a top-level class, which is a standalone class defined in a .java file, but you can protect an inner one. This highlights the importance of proper package decomposition.
Now, let's contrast protected with its adjacent modifiers, private and "package-private" (default).
Protected vs default
Think of classes from the same package as neighbors and subclasses as children of a particular class. There are some things you can share or do with your neighbors, for example, discuss a maintenance plan or share the basement. These things and actions would be package-private (default).
There are also things you can do for children or close friends, like lending money or enjoying a park trip on a Sunday. These actions would fall under the protected category.
Protected vs private
This distinction is even simpler: if a variable, a method, or an inner class is used solely by the class itself, then it is private; otherwise, it is protected. Remember this guideline:
Use the most restrictive access level that fits for a particular member.
If you're unsure about the need for other classes to use the method, start by making it private. You can always grant more access later if needed.
Example
Now let's see how all of this works in practice. In the example below, the package org.hyperskill.bluetooth has three classes: Laptop, SmartPhone, and SmartWatch. All the gadgets in the package can be connected via Bluetooth. Laptop has a method receiveInfo(), responsible for getting any information from connected gadgets.
package org.hyperskill.bluetooth;
public class Laptop {
private String info;
void receiveInfo(String info) {
this.info = info;
}
}
The Laptop class has only a single field info which is not directly accessible since it is declared as private. But all classes from the same package can access it invoking the receiveInfo method which is declared as package-private (no modifier).
We consider that SmartPhone and SmartWatch classes extend the same MobileGadget class with the printNotification method:
package org.hyperskill.bluetooth;
public class MobileGadget {
protected void printNotification(String data) {
System.out.println(data);
}
}
The printNotification method is accessible for all subclasses of this class as well as for all classes in the same package (including the Laptop class).
The SmartPhone class can access the receiveInfo method of the Laptop class and the printNotification method of the MobileGadget class.
package org.hyperskill.bluetooth;
public class SmartPhone extends MobileGadget {
private Laptop connectedLaptop;
public SmartPhone() {
this.connectedLaptop = new Laptop();
}
private void sendInfoToLaptop(String info) {
printNotification("Sending info to laptop : " + info);
connectedLaptop.receiveInfo(info);
}
}
The SmartWatch class has a private method countHeartRate, which is not available to other classes (even from a “brother” class SmartPhone). It also uses the Laptop's method of receiving info and a parent's method to print the notification:
package org.hyperskill.bluetooth;
public class SmartWatch extends MobileGadget {
private int avgHeartRate;
private Laptop connectedLaptop;
public SmartWatch() {
this.avgHeartRate = 75;
this.connectedLaptop = new Laptop();
}
private int countHeartRate() {
System.out.println("Counting heart rate");
return avgHeartRate;
}
private void sendInfoToLaptop(String info) {
printNotification("Sending info to laptop : " + info);
connectedLaptop.receiveInfo(info);
}
}
We hope all modifiers are clear now!
The complete code example is available on GitHub. It has a slightly different package structure which is closer to a real project. You can navigate it in the GitHub web interface. You can copy this code and try to change it to better understand the example.
Let's recap
Now, it's time to put all the access modifiers together:
The scheme is the same as it was earlier, but the questions now are specified with regard to inheritance.
Conclusion
In this topic, you learned about the protected access modifier, its position among the other access modifiers, and how it differs from the private and "package-private" (default) modifiers. We also saw how the modifiers work in an example and how to choose between them. Now, it's time to practice!