Theory:Protected modifier
As you may remember, an access modifier describes who can use your piece of code. There are 4 of them in Java:
private
: available only for the class itself;default
: available for classes from the same package (= package-private);protected
: available for classes from the same package and the extending classes.public
: available from everywhere;
We've already considered most of them, but there's the most interesting one left: the protected
access modifier. Let's place it among the modifiers you already know:
This modifier determines that only subclasses and any classes from the same package can use a class member. A top-level class, which is a non-nested independent class defined in a .java
file, cannot be protected, but an inner one can be declared this way. This is where the importance of a proper package decomposition comes in.
Now let's discuss the difference between protected
and its scale neighbors, private
and "package-private" (default
).
# Protected vs default
You can think of classes from the same package as the neighbors and subclasses as the 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 and close friends, like borrow some money or go for a walk in a park on Sunday. These things will be protected
.
# Protected vs private
This distinction is even easier: if a variable, a method, or an inner class is used only by the class itself, then it is private
, otherwise, it is protected
. Following the main rule:
Use the most restrictive access level that makes sense for a particular member.
If you're not sure whether the method is useful for other classes, it’s better to first make it private and expand its availability 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;
}
}
2
3
4
5
6
7
8
9
10
11
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);
}
}
2
3
4
5
6
7
8
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 data) {
printNotification("Sending data to laptop : " + data);
connectedLaptop.receiveInfo(data);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
The SmartWatch
class has a private method countHeartRate
, which is not available from other classes (even from a “brother” class SmartPhone
). It also uses the Laptop
's method of receiving data 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 data) {
printNotification("Sending data to laptop : " + data);
connectedLaptop.receiveInfo(data);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
We hope all modifiers are clear now!
The complete code example is available on GitHub (opens new window). 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 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!