Java SE: static modifier
Java Fundamentals
📘 static modifier
In Java, the static
modifier is used to indicate that a class or class member belongs to the class itself, rather than to an instance of the class.
In other words, the static
modifier indicates that the class or class member is associated with the class as a whole, rather than with a specific instance of the class.
1 static
modifier
Classical use and basic example of static method
, we call within the class
our static
method
just using the name of the method printArea()
:
The static
modifier has several different uses in Java, depending on where it is applied. Here are some examples of how the static
modifier can be used in Java.
1.1 static
code block
In Java, we have a special block known as aStatic Initialization Block
. A Static Initialization Block
is executed before the main()
method, it will execute once. This block will not return anything and we can not use the this
keyword since it does not have any instance.
For example:
1.2 static
field
When applied to a field, the static
modifier indicates that the field belongs to the class itself, rather than to an instance of the class. This means that all instances of the class share the same value for the static
field.
For example:
Counter.java
In this example, the count
field is marked as static
, which means that all instances of the Counter
class share the same value for the count
field. When a new instance of the Counter
class is created, the count
field is incremented, and the new value is shared by all instances of the class.
Another example:
Account.java
public class Account {
// Static field
private static int nextAccountNumber = 1;
// Private instance variables
private int accountNumber;
private String name;
private double balance;
// Constructor
public Account(String name, double balance) {
this.accountNumber = nextAccountNumber++;
this.name = name;
this.balance = balance;
}
// Getter method for the accountNumber field
public int getAccountNumber() {
return accountNumber;
}
// Getter method for the name field
public String getName() {
return name;
}
// Getter method for the balance field
public double getBalance() {
return balance;
}
// Method for depositing money into the account
public void deposit(double amount) {
balance += amount;
}
// Method for withdrawing money from the account
public void withdraw(double amount) {
balance -= amount;
}
}
In this example, the Account
class defines a nextAccountNumber
field that is marked as static
. This means that the nextAccountNumber
field belongs to the Account
class itself, rather than to an instance of the Account
class. This means that all instances of the Account
class share the same value for the nextAccountNumber
field.
When a new instance of the Account
class is created, the nextAccountNumber
field is incremented, and the new value is shared by all instances of the class. This allows each instance of the Account
class to have a unique accountNumber
field, which is generated automatically using the nextAccountNumber
field.
1.3 static
method
When applied to a method, the static
modifier indicates that the method belongs to the class itself, rather than to an instance of the class. This means that the static
method can be called on the class itself, rather than on an instance of the class.
For example:
MathUtils.java
In this example, the squareRoot()
method is marked as static
, which means that it can be called on the MathUtils
class itself, rather than on an instance of the MathUtils
class. This allows the squareRoot()
method to be called without creating an instance of the MathUtils
class, which can be useful in some situations.
For example:
MovieManager.java
public class MovieManager {
// Static method
public static boolean createMovie(Movie movie) {
boolean result = false;
// to-do algorithmic to solve this method
return result;
}
// Static method
public static boolean deleteMovie(String idMovie) {
boolean result = false;
// to-do algorithmic to solve this method
return result;
}
// Static method
public static boolean updateMovie(Movie movie) {
boolean result = false;
// to-do algorithmic to solve this method
return result;
}
// Static method
public static List<Movie> getAllMovies() {
List<Movie> movies = new ArrayList<>();
// to-do algorithmic to solve this method
return movies;
}
// Static method
public static List<Movie> findMovie(String title) {
List<Movie> movies = new ArrayList<>();
// to-do algorithmic to solve this method
return movies;
}
}
1.4 static
class
When applied to a class, the static
modifier indicates that the class is a nested class. In other words, the static
class is defined inside another class, and is associated with the outer class.
Account.java
public class Account {
// Static field
private static int nextAccountNumber = 1;
// Private instance variables
private int accountNumber;
private String name;
private double balance;
// Static nested class
public static class Transaction {
// Private instance variables
private int transactionNumber;
private double amount;
private String type;
// Constructor
public Transaction(double amount, String type) {
this.transactionNumber = nextAccountNumber++;
this.amount = amount;
this.type = type;
}
// Getter method for the transactionNumber field
public int getTransactionNumber() {
return transactionNumber;
}
// Getter method for the amount field
public double getAmount() {
return amount;
}
// Getter method for the type field
public String getType() {
return type;
}
}
// Constructor
public Account(String name, double balance) {
this.accountNumber = nextAccountNumber++;
this.name = name;
this.balance = balance;
}
// Getter method for the accountNumber field
public int getAccountNumber() {
return accountNumber;
}
// Getter method for the name field
public String getName() {
return name;
}
// Getter method for the balance field
public double getBalance() {
return balance;
}
}
Here is an example of how the static
modifier can be used when applied to a class
in Java
, using an Account
class and a nested Transaction
class as examples:
2 static
scope
In Java SE (Standard Edition), the term “static scope” typically refers to the visibility and accessibility of variables and methods marked with the static
keyword within a class or interface.
When a variable or method is declared as static
within a class or interface, it means that it belongs to the class itself rather than to instances of the class. This has implications for how these members are accessed:
Visibility within the class: Static variables and methods can be accessed directly within other static methods or variables of the same class without needing an instance of the class.
Access from outside the class: Static variables and methods can also be accessed directly using the class name, without needing an instance of the class. This access can occur from other classes, as long as the static member is declared with appropriate access modifiers (e.g.,
public
,protected
, orprivate
).Lifetime: Static variables exist for the entire duration of the program’s execution, and there is only one instance of each static variable per class, shared by all instances of the class.
Initialization: Static variables are initialized only once, at the start of the program execution, before any instances of the class are created.
Here’s a basic example to illustrate static scope:
Account.java
public class MyClass {
// Static variable
public static int staticVariable = 10;
// Instance variable
public int instanceVariable;
// Static method
public static void staticMethod() {
System.out.println("This is a static method.");
// Can access static variables directly
System.out.println("Static variable: " + staticVariable);
// Cannot access instance variables directly
// System.out.println("Instance variable: " + instanceVariable); // This line would cause a compilation error
}
// Instance method
public void instanceMethod() {
System.out.println("This is an instance method.");
// Can access both static and instance variables directly
System.out.println("Static variable: " + staticVariable);
System.out.println("Instance variable: " + instanceVariable);
}
}
In this example, staticVariable
is a static variable that can be accessed directly within both staticMethod()
and instanceMethod()
, while instanceVariable
is an instance variable that can only be accessed within instanceMethod()
or other instance methods, requiring an instance of MyClass
.
3 static
vs. non-static
3.0.1 Pros & cons usage static
methods
Pros of making a method static | Cons of making a method static |
---|---|
Can be called directly on the class, without needing to create an instance | Cannot access non-static fields and methods of the class |
Can be used as utility methods that don’t depend on the state of an object | Can only work with the parameters passed to it and not use information unique to each object or instance |
Can be used to access only static variables and methods, making it more efficient | Can be challenging to make sure all instances of a class are modified consistently when using static methods |
3.0.2 Pros & cons usage non-static
methods
Pros of making a method non-static | Cons of making a method non-static |
---|---|
Can access both static and non-static fields and methods of the class, allowing it to use the state of an object to determine its behavior | Can only be called on an instance of the class, so you need to create an object of a class before using the method |
Are associated with an instance of the class, so they can use the information that is unique to each object | Can cause confusion when working with non-static methods because it could be called on different instances, which could cause unexpected behavior |
Object-oriented design principles promote the use of non-static methods because they can be overridden by subclasses to change their behavior |
4 final
modifier
The final
modifier in Java
is a powerful keyword used to restrict the modification of variables, methods, and classes.
The final
modifier in Java is a powerful keyword used to restrict the modification of variables, methods, and classes. Here’s an overview of how it works:
Final
Variables
When applied to variables, the final
modifier creates constants that cannot be reassigned once initialized.
- For primitive types, the value cannot be changed.
- For reference types, the reference cannot be changed, but the object’s contents can still be modified.
final int MAX_VALUE = 100;
final List<String> names = new ArrayList<>();
// Valid: Modifying the list's contents
names.add("Alice");
// Invalid: Attempting to reassign the variable
// MAX_VALUE = 200; // Compilation error
// names = new ArrayList<>(); // Compilation error
Final
Methods
A final
method cannot be overridden by subclasses. This is useful for preserving critical functionality or preventing unexpected behavior in inherited classes.
class Parent {
final void display() {
System.out.println("This method cannot be overridden");
}
}
class Child extends Parent {
// Invalid: Attempting to override a final method
// void display() { } // Compilation error
}
Final
Classes
A final
class cannot be extended or inherited. This is often used to create immutable classes or to prevent unintended modifications to a class’s behavior.
final class ImmutableClass {
// Class implementation
}
// Invalid: Attempting to extend a final class
// class Subclass extends ImmutableClass { } // Compilation error
4.1 Key Points
Final
variables must be initialized either at declaration or in the constructor.Static
final variables are often used to define constants.- Final methods in
interfaces
are redundant, asinterface
methods are implicitly final. - The
final
keyword can improve performance in some cases, as the compiler can optimize final methods and variables.
5 static
/ final
Modifier | Use Case | Description | Example |
---|---|---|---|
static |
Class members | Belongs to the class rather than instances | public static int count = 0; |
static |
Utility methods | Methods that don’t require instance state | public static int add(int a, int b) { return a + b; } |
static |
Constants | Class-level constants (usually combined with final ) |
public static final double PI = 3.14159; |
static |
Static blocks | Code executed when class is loaded | static { System.out.println("Class loaded"); } |
final |
Variables | Creates constants that can’t be reassigned | final int MAX_SIZE = 100; |
final |
Methods | Prevents method overriding in subclasses | public final void display() { } |
final |
Classes | Prevents class inheritance | public final class ImmutableString { } |
final |
Method parameters | Prevents parameter reassignment within method | public void process(final int value) { } |
static final |
Class constants | Immutable class-level constants | public static final String VERSION = "1.0"; |
Somethimes we use static
and final together
, an example demonstrating the use of final static
variables in Java:
public class MathConstants {
public static final double PI = 3.14159265359;
public static final double E = 2.71828182846;
public static final double GOLDEN_RATIO = 1.61803398875;
public static void main(String[] args) {
System.out.println("Value of PI: " + PI);
System.out.println("Value of E: " + E);
System.out.println("Value of Golden Ratio: " + GOLDEN_RATIO);
// The following lines would cause compilation errors if uncommented:
// PI = 3.14; // Error: cannot assign a value to final variable PI
// E = 2.72; // Error: cannot assign a value to final variable E
}
}
In this example:
We declare three
public static final
variables:PI
,E
, andGOLDEN_RATIO
. These are mathematical constants that should never change[2][4].The
static
keyword means these variables belong to the class itself, not to any specific instance of the class. They can be accessed directly through the class name, likeMathConstants.PI
[3].The
final
keyword ensures that these variables cannot be reassigned once they are initialized. This makes them true constants.We initialize these constants at the point of declaration. For
final static
variables, this is one of the valid ways to initialize them.In the
main
method, we print out the values of these constants.The commented-out lines demonstrate that attempting to reassign these constants would result in a compilation error.
Key points about final static
variables:
- They must be initialized either at the point of declaration or in a static initializer block.
- They are often used for constants that are shared across all instances of a class.
- By convention,
final static
variables are usually named in ALL_CAPS with underscores separating words. - They are evaluated at compile-time, which can lead to performance optimizations.
Using final static
variables for constants provides several benefits: - It ensures the value cannot be changed accidentally. - It clearly communicates the intent that this value should not change. - It allows the compiler to perform optimizations, potentially improving performance.
Remember, while
final
prevents reassignment, if the constant is an object reference, the object’s internal state can still be modified unless the object itself is immutable.
6 final
and immutable
The key differences between final
and immutable in Java are:
6.1 Final
- Applies to variables, methods, and classes.
- For variables, prevents reassignment of the reference, but not modification of the object’s state.
- Ensures the variable will always point to the same object reference.
6.2 Immutable
- Applies to objects, not variables.
- Prevents any changes to the object’s state after creation.
- The object’s internal values cannot be modified once initialized.
6.3 Key Distinctions
Scope:
final
is about reference constancy, while immutability is about object state constancy.Mutability: A
final
variable can still refer to a mutable object, whereas an immutable object’s state cannot be changed at all.Implementation:
final
is a keyword in Java, while immutability is a design principle implemented by the programmer.Flexibility: You can have a non-final reference to an immutable object, allowing the reference to be reassigned while the object remains unchangeable.
Combination: An object can be both
final
and immutable, like theString
class in Java.