Welcome to this lesson on static members in Java! As you delve deeper into object-oriented programming, understanding static is crucial. The static keyword is a non-access modifier in Java that applies to members of a class: fields (variables), methods, blocks, and even nested classes. It fundamentally changes how these members behave and how they are associated with the class.

In essence, when a member is declared static, it belongs to the class itself, rather than to any specific instance (object) of that class. This means that a static member is shared by all objects of that class. Let's break this down.

1. Static Variables (Class Variables)

A static variable is also known as a class variable. Unlike instance variables (which belong to each object), a single copy of a static variable is created and shared among all instances of the class.

Key Characteristics:

  • Belongs to the class: You access it using the class name, not an object reference (e.g., ClassName.staticVariable).

  • One copy: All objects of the class share the same static variable. If one object changes it, the change is reflected for all other objects.

  • Memory allocation: Static variables are allocated memory only once when the class is loaded into memory.

When to use them:

  • When you need a variable that is common to all objects of a class.

  • For constants that are shared across all instances (e.g., Math.PI).

  • For counters that track the number of objects created.

Example:

Consider a scenario where you want to keep track of the total number of students created in a system, or a common school name.

public class Student {
    // Instance variable: Each student object will have its own name
    String name;

    // Static variable: Shared by all Student objects
    static String schoolName = "Tech High School";

    // Static variable: Counter for the number of students created
    static int studentCount = 0;

    public Student(String name) {
        this.name = name;
        studentCount++; // Increment static counter each time a new student is created
    }

    public void displayStudentInfo() {
        System.out.println("Student Name: " + this.name);
        System.out.println("School: " + Student.schoolName); // Access static variable using class name
        System.out.println("Total Students (so far): " + Student.studentCount);
        System.out.println("---");
    }

    public static void main(String[] args) {
        // Accessing static variable before creating any objects
        System.out.println("Initial Student Count: " + Student.studentCount);
        System.out.println("School Name: " + Student.schoolName);
        System.out.println("---");

        Student s1 = new Student("Alice");
        s1.displayStudentInfo();

        Student s2 = new Student("Bob");
        s2.displayStudentInfo();

        // We can change the static variable through the class name or any object (though class name is preferred)
        Student.schoolName = "Global Academy";
        System.out.println("School name changed to: " + Student.schoolName);
        System.out.println("---");

        Student s3 = new Student("Charlie");
        s3.displayStudentInfo(); // All students now reflect the new school name

        System.out.println("Final Student Count: " + Student.studentCount);
    }
}

Explanation:

  • schoolName and studentCount are static. They belong to the Student class.

  • When s1, s2, and s3 are created, they all share the same studentCount and schoolName.

  • Changing Student.schoolName affects all instances.

2. Static Methods (Class Methods)

A static method is also known as a class method. These methods belong to the class rather than any specific object. You can call them directly using the class name, without creating an instance of the class.

Key Characteristics:

  • Belongs to the class: You call it using ClassName.staticMethod().

  • Cannot use this or super: Static methods operate independently of any specific object, so they cannot refer to instance variables or instance methods directly using this or super keywords.

  • Can only access static members: A static method can directly call other static methods and access static variables of the same class. To access instance members, you would need an object reference.

  • Memory allocation: Static methods are loaded into memory along with the class.

When to use them:

  • Utility methods that perform operations not dependent on any particular object's state (e.g., Math.max(), Integer.parseInt()).

  • Methods that only need to access static variables.

  • Factory methods that return an instance of the class.

Example:

Let's add a utility method to our Student class that doesn't need a specific student object to perform its function.

public class Calculator {
    // Static method for addition
    public static int add(int a, int b) {
        return a + b;
    }

    // Static method to display a generic message
    public static void displayWelcomeMessage() {
        System.out.println("Welcome to the Calculator!");
    }

    public static void main(String[] args) {
        // Calling static methods using the class name
        Calculator.displayWelcomeMessage();

        int sum = Calculator.add(10, 5);
        System.out.println("Sum: " + sum);

        int product = multiply(7, 8); // Can call static method directly within the same class's static method
        System.out.println("Product: " + product);

        // Attempting to call a non-static method or access a non-static variable directly would cause an error
        // int x = nonStaticVar; // Error: Cannot make a static reference to the non-static field nonStaticVar
        // nonStaticMethod(); // Error: Cannot make a static reference to the non-static method nonStaticMethod()
    }

    // Another static method
    public static int multiply(int a, int b) {
        return a * b;
    }

    // Non-static (instance) variable and method for demonstration of restrictions
    // int nonStaticVar = 100;
    // public void nonStaticMethod() {
    //     System.out.println("This is a non-static method.");
    // }
}

Explanation:

  • add() and displayWelcomeMessage() are static methods.

  • They are called directly using Calculator.add() and Calculator.displayWelcomeMessage().

  • Notice how multiply() is called directly within main() because both are static methods within the same class.

3. Static Blocks

A static block is a special block of code that is executed only once when the class is loaded into memory. It's primarily used for initializing static variables.

Key Characteristics:

  • Execution: Executed exactly once when the class is first loaded.

  • Purpose: Primarily used to initialize static variables that require some logic (e.g., reading from a file, performing complex calculations).

  • Placement: Can appear anywhere within the class.

Example:

public class ApplicationSettings {
    static String appVersion;
    static String databaseConnectionUrl;
    static int maxConnections;

    // Static block for initializing static variables
    static {
        System.out.println("Static block executed: Initializing application settings...");
        appVersion = "1.0.0";
        databaseConnectionUrl = "jdbc:mysql://localhost:3306/appdb";
        maxConnections = 50;

        // You could perform more complex initialization here, like reading from a config file
        System.out.println("Settings initialized successfully.");
        System.out.println("--------------------");
    }

    public static void displaySettings() {
        System.out.println("Application Version: " + appVersion);
        System.out.println("Database URL: " + databaseConnectionUrl);
        System.out.println("Max Connections: " + maxConnections);
        System.out.println("--------------------");
    }

    public static void main(String[] args) {
        System.out.println("Main method started.");
        // The static block will execute before this line if the class hasn't been loaded yet.

        ApplicationSettings.displaySettings(); // Accessing a static method will trigger class loading

        // If we access a static variable directly, it also triggers class loading (and thus static block execution)
        System.out.println("App Version from direct access: " + ApplicationSettings.appVersion);

        // Creating an object also triggers static block if not already executed
        // ApplicationSettings settings = new ApplicationSettings();
    }
}

Explanation:

  • The code inside the static { ... } block runs as soon as ApplicationSettings class is loaded. This happens when you first try to access any static member of ApplicationSettings (like ApplicationSettings.displaySettings() or ApplicationSettings.appVersion), or when you create the first object of this class.

4. Static Nested Classes

Java also allows you to define a class inside another class. When a nested class is declared static, it's called a static nested class.

Key Characteristics:

  • No outer object dependency: A static nested class does not require an instance of its outer class to be created. It behaves like a top-level class.

  • Access to outer members: It can only access static members of the outer class directly. To access non-static members of the outer class, it needs an instance of the outer class.

  • Use cases: Often used to group related classes that only make sense together, without implicitly linking the inner class to an outer object's state.

Example (Conceptual - typically covered in more advanced topics):

class OuterClass {
    static int outerStaticVar = 10;
    int outerInstanceVar = 20;

    static class StaticNestedClass {
        void display() {
            System.out.println("From Static Nested Class:");
            System.out.println("Outer Static Var: " + OuterClass.outerStaticVar);
            // System.out.println("Outer Instance Var: " + outerInstanceVar); // ERROR: Cannot access non-static member directly
        }
    }

    public static void main(String[] args) {
        OuterClass.StaticNestedClass nested = new OuterClass.StaticNestedClass();
        nested.display();
    }
}

Explanation:

  • StaticNestedClass is a static nested class inside OuterClass.

  • You can create an instance of StaticNestedClass without creating an instance of OuterClass.

  • It can access outerStaticVar directly because it's static, but not outerInstanceVar directly.

Key Takeaways

  • static means "belongs to the class," not to an object.

  • Static variables are shared by all objects of the class (one copy for the entire class).

  • Static methods can be called using the class name and cannot directly access instance members (variables or methods) of the same class without an object.

  • Static blocks are executed once when the class is loaded, typically for static member initialization.

  • main() method is always static because it needs to be called by the Java Virtual Machine (JVM) without creating an object of your class.

Exercise

To solidify your understanding, try the following exercise:

Problem: Create a Java class called BankAccount with the following:

  1. An instance variable accountNumber (String).

  2. An instance variable balance (double).

  3. A static variable nextAccountNumber (int) initialized to 1001. This variable should automatically assign a unique accountNumber to each new BankAccount object.

  4. A static variable totalAccountsCreated (int) to keep track of how many bank accounts have been created.

  5. A constructor that takes an initial balance, assigns nextAccountNumber as the accountNumber to the new account, and then increments nextAccountNumber and totalAccountsCreated.

  6. An instance method deposit(double amount) that adds the amount to the balance.

  7. An instance method withdraw(double amount) that subtracts the amount from the balance (ensure balance doesn't go below zero).

  8. An instance method getAccountInfo() that prints the accountNumber and balance for that specific account.

  9. A static method displayTotalAccounts() that prints the total number of accounts created using totalAccountsCreated.

Instructions:

  • Write the BankAccount class.

  • In a main method (which must be static), create at least three BankAccount objects.

  • Perform some deposits and withdrawals on these accounts.

  • Call getAccountInfo() for each account.

  • Finally, call the displayTotalAccounts() static method to see the total.

Good luck! This exercise will help you distinguish between static and instance members and understand their practical applications.

Key Takeaways

  • It means a member belongs to the class itself, not to any specific object (instance) of that class

  • There's only one copy of a static variable, shared by all objects of the class. Changes to it are seen by everyone.

  • These methods are called using the class name (e.g., ClassName.staticMethod()). They cannot directly access instance (non-static) variables or methods without an object reference.

  • Code inside a static block executes only once when the class is first loaded into memory, usually for initializing static variables.

  • It's static because the Java Virtual Machine (JVM) needs to call it without creating an object of your class.

Quiz