Java provides many modifiers, which are mainly divided into two categories:
- Access modifiers
- Non-access modifiers
Modifiers are used to define classes, methods, or variables, and are usually placed at the beginning of a statement. We illustrate this with the following example:
public class ClassName{}
private boolean myFlag;
static final double weeks = 9.5;
protected static final int BOXWIDTH = 42;
public static void main(String[]arguments){}
Access Control Modifiers
In Java, access control modifiers can be used to protect access to classes, variables, methods, and constructors. Java supports 4 different access levels.
- default (i.e., default, no keyword written): Visible within the same package, no modifier is used. Used for: classes, interfaces, variables, methods.
- private: Visible within the same class. Used for: variables, methods. Note: Cannot be used to modify classes (outer classes)
- public: Visible to all classes. Used for: classes, interfaces, variables, methods.
- protected: Visible to classes within the same package and all subclasses. Used for: variables, methods. Note: Cannot be used to modify classes (outer classes).
We can illustrate access permissions with the following table:
| Access Control | Modifier | Current Class | Same Package | Subclass (Same Package) | Subclass (Different Package) | Other Package |
|---|---|---|---|---|---|---|
public |
Y | Y | Y | Y | Y | |
protected |
Y | Y | Y | Y/N (Explanation) | N | |
default |
Y | Y | Y | N | N | |
private |
Y | N | N | N | N |
Default Access Modifier - No Keyword Used
If no access modifier is specified in the definition of a class, variable, method, or constructor, they are given the default access modifier by default.
The access level of the default access modifier is package-level, meaning it is only accessible by other classes within the same package.
As shown in the following example, the declarations of variables and methods can be made without any modifier.
Example
class MyClass {
int x = 10;
void display() {
System.out.println("Value of x is: " + x);
}
}
class MyOtherClass {
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.display();
}
}
In the above example, the MyClass class and its member variable x and method display() are defined using the default access modifier. The MyOtherClass class is in the same package, so it can access the MyClass class and its member variables and methods.
Private Access Modifier - private
The private access modifier is the strictest access level. Therefore, methods, variables, and constructors declared as private can only be accessed within the declaring class. Classes and interfaces cannot be declared as private.
Variables declared as private can only be accessed by external classes through public getter methods in the class.
The use of the private access modifier is mainly to hide the implementation details of a class and protect the class's data.
The following class uses the private access modifier:
public class Logger {
private String format;
public String getFormat() {
return this.format;
}
public void setFormat(String format) {
this.format = format;
}
}
In the example, the format variable in the Logger class is a private variable, so other classes cannot directly get and set the value of this variable. To allow other classes to manipulate this variable, two public methods are defined: getFormat() (returns the value of format) and setFormat(String) (sets the value of format).
Public Access Modifier - public
Classes, methods, constructors, and interfaces declared as public can be accessed by any other class.
If several public classes that access each other are distributed in different packages, the package containing the corresponding public class needs to be imported. Due to class inheritance, all public methods and variables of a class can be inherited by its subclasses.
The following function uses public access control:
public static void main(String[] arguments) {}
The main() method of a Java program must be set to public; otherwise, the Java interpreter will not be able to run the class.
Protected Access Modifier - protected
protected needs to be analyzed and explained from the following two points:
- Subclass and base class are in the same package: Variables, methods, and constructors declared as protected can be accessed by any other class in the same package;
- Subclass and base class are not in the same package: Then in the subclass, the subclass instance can access the protected methods it inherits from the base class, but cannot access the protected methods of the base class instance.
protected can modify data members, constructors, and method members, but cannot modify classes (except inner classes).
Interfaces and their member variables and member methods cannot be declared as protected. You can see the demonstration in the following figure:
Subclasses can access methods and variables declared with the protected modifier, thus protecting unrelated classes from using these methods and variables.
The following parent class uses the protected access modifier, and the subclass overrides the parent class's openSpeaker() method.
class AudioPlayer {
protected boolean openSpeaker(Speaker sp) {
}
}
class StreamingAudioPlayer extends AudioPlayer {
protected boolean openSpeaker(Speaker sp) {
}
}
If the openSpeaker() method is declared as private, then no other class except AudioPlayer will be able to access this method.
If openSpeaker() is declared as public, then all classes will be able to access this method.
If we only want this method to be visible to its subclasses, we declare the method as protected.
protected is the most difficult Java class member access modifier to understand. For more details, please see Detailed Explanation of Java protected Keyword.
Access Control and Inheritance
Please note the following rules for method inheritance:
- Methods declared as public in the parent class must also be public in the subclass.
- Methods declared as protected in the subclass must be declared as either protected or public in the subclass, and cannot be declared as private.
- Methods declared as private in the parent class cannot be inherited by subclasses.
Non-Access Modifiers
To implement some other functions, Java also provides many non-access modifiers.
The static modifier is used to modify class methods and class variables.
The final modifier is used to modify classes, methods, and variables. Classes modified with final cannot be inherited, methods modified with final cannot be redefined by inheriting classes, and variables modified with final are constants and cannot be modified.
The abstract modifier is used to create abstract classes and abstract methods.
The synchronized and volatile modifiers are mainly used for thread programming.
static Modifier
- Static Variables:
The static keyword is used to declare static variables that are independent of objects. No matter how many objects of a class are instantiated, there is only one copy of its static variables. Static variables are also called class variables. Local variables cannot be declared as static variables.
- Static Methods:
The static keyword is used to declare static methods that are independent of objects. Static methods cannot use non-static variables of the class. Static methods get data from the parameter list and then calculate this data.
Access to class variables and methods can be done directly using classname.variablename and classname.methodname.
As shown in the following example, the static modifier is used to create class methods and class variables.
public class InstanceCounter {
private static int numInstances = 0;
protected static int getCount() {
return numInstances;
}
private static void addInstance() {
numInstances++;
}
InstanceCounter() {
InstanceCounter.addInstance();
}
public static void main(String[] arguments) {
System.out.println("Starting with " + InstanceCounter.getCount() + " instances");
for (int i = 0; i < 500; ++i) {
new InstanceCounter();
}
System.out.println("Created " + InstanceCounter.getCount() + " instances");
}
}
The above example runs and edits the result as follows:
Starting with 0 instances
Created 500 instances
final Modifier
final Variable:
final means "last, final". Once a variable is assigned, it cannot be reassigned. Instance variables modified by final must be explicitly assigned an initial value.
The final modifier is often used with the static modifier to create class constants.
Example
public class Test {
final int value = 10;
public static final int BOXWIDTH = 6;
static final String TITLE = "Manager";
public void changeValue() {
value = 12;
}
}
final Method
Final methods in the parent class can be inherited by subclasses, but cannot be overridden by subclasses.
The main purpose of declaring a final method is to prevent the content of the method from being modified.
As shown below, use the final modifier to declare a method.
public class Test {
public final void changeName() {}
}
final Class
Final classes cannot be inherited, and no class can inherit any characteristics of a final class.
Example
public final class Test {}
abstract Modifier
Abstract Class:
Abstract classes cannot be used to instantiate objects. The only purpose of declaring an abstract class is to extend it in the future.
A class cannot be modified by both abstract and final. If a class contains abstract methods, then the class must be declared as abstract, otherwise a compilation error will occur.
Abstract classes can contain abstract methods and non-abstract methods.
Example
abstract class Caravan {
private double price;
private String model;
private String year;
public abstract void goFast();
public abstract void changeColor();
}
Abstract Method
An abstract method is a method with no implementation. The specific implementation of this method is provided by the subclass.
Abstract methods cannot be declared as final and static.
Any subclass that inherits an abstract class must implement all abstract methods of the parent class, unless the subclass is also an abstract class.
If a class contains several abstract methods, then the class must be declared as abstract. An abstract class may not contain abstract methods.
The declaration of an abstract method ends with a semicolon, for example: public abstract sample();.
Example
public abstract class SuperClass {
abstract void m();
}
class SubClass extends SuperClass {
void m() {
.........
}
}
synchronized Modifier
Methods declared with the synchronized keyword can only be accessed by one thread at a time. The synchronized modifier can be applied to the four access modifiers.
Example
public synchronized void showDetails() {
.......
}
transient Modifier
When a serialized object contains an instance variable modified by transient, the Java Virtual Machine (JVM) skips that particular variable.
This modifier is included in the statement that defines the variable, used to preprocess the data types of classes and variables.
Example
public transient int limit = 55;
public int b;
volatile Modifier
The member variable modified by volatile is forced to be re-read from shared memory every time it is accessed by a thread. Moreover, when the member variable changes, the thread is forced to write the changed value back to shared memory. This way, at any moment, two different threads always see the same value of a certain member variable.
A volatile object reference may be null.
Example
public class MyRunnable implements Runnable {
private volatile boolean active;
public void run() {
active = true;
while (active) {
}
}
public void stop() {
active = false;
}
}
Usually, one thread calls the run() method (in the thread started by Runnable), and another thread calls the stop() method. If the active value in the buffer in the first line is used, then the loop will not stop when the active value in the second line is false.
However, in the above code, we used volatile to modify active, so the loop will stop.
YouTip