Static Modifier and Nested Classes Notes

Static Variables

  • Each instance of a class created with new creates a copy of all instance variables.

  • Example:

    public class Employee {
        private String lastname;
        private String firstname;
        // some code here
    }
    
    // create two Employees in the main method
    Employee e1 = new Employee("Reyes", "Mark");
    Employee e2 = new Employee("Santos", "John");
    
  • In the Employee class, a unique copy of lastname and firstname is created for each new Employee object.

  • static is a keyword that modifies the association of an item to a class.

  • Static items are shared across all instances of the class.

  • Instances share one copy of the static items, and each has its own unique copies of instance (non-static) items.

  • Static variables:

    • Are also known as class variables.
    • Are declared with the static keyword.
    • Have only one copy in memory, unlike instance variables, which have one copy per instance.
    • Are shared by object instances.
    • Hold the same value for all class instances.
  • Static variables can be public, protected, default, or private.

  • If public, they can be modified directly by other classes; consider using final to make them constant.

  • Example: public static final int MODEL_NUM = 883;

  • It's good practice to initialize static variables to avoid relying on default null and 0 values.

  • Values can be changed as long as the class is active in JVM memory.

  • Garbage collection removes it from memory, and the initial values assigned will return the next time you use it.

  • Static variables that are not final can be read or assigned new values using this in instance methods.

    • Changes made by instance methods affect all instances.
    • A change to a static variable may indicate the Singleton pattern (limiting the class to only one object).
  • Example:

    private static String myCompany = "Oracle";
    
    public void setMyCompany(String s) {
        this.mycompany = s;
    }
    
  • Examples of initializing and accessing a static variable:

    public class Turtle {
        public static String food = "Turtle Food";
        private int age;
    public Turtle(int age) {
        this.age = age;
    }
    
    }
  • The Turtle class contains a static variable food and a private instance variable age.

  • food is static because all turtles eat the same food.

  • age is an instance variable because each turtle has a different age.

  • Instance variables require an instance of the class to exist before access is possible.

Accessing Static Variables

  • You can access static variables without creating an instance of the class.

  • Example:

    System.out.println("I feed " + Turtle.food + " to all my turtles!");
    
  • Generally, static variables are accessed using the notation: ClassName.variableName;

Static Methods

  • Static (or class) methods exist once and are shared by all class instances.

  • They:

    • May be used by other class methods or instance methods based on their access modifier.
    • Cannot access non-static (instance) variables.
    • Can only access static variables.
    • Cannot access non-static (instance) methods.
    • Can only access other static methods.
    • Can be redefined in subclasses.
    • Can be public, protected, default, or private.
  • Differences between calling an instance method versus a static method:

    • Instance method: create an instance and use dot notation.
    • Static method: use the class name, dot notation, and static method name.
  • The static method provides a wrapper to construct an instance of a class.

  • When the class has a private access constructor, a static method is one way to create an instance of the class.

  • Example:

    public class Turtle {
        public static String food = "Turtle Feed";
        public int age;
        public int tankNum;
        public static int numTanks = 3;
    public Turtle(int age) {
        this.age = age;
        tankNum = (int) ((Math.random() * numTanks) + 1);
    }
    
    public void swim() {
        // implementation
    }
    
    public int getAge() {
        return age;
    }
    
    public int getTankOfResidence() {
        return tankNum;
    }
    
    public static String fishTank() {
        return "I have " + numTanks + " fish tanks.";
    }
    
    }
  • The Turtle class has a static variable numTanks and an instance variable tankNum.

  • swim() is an instance method; turtles may swim differently depending on their age.

  • getAge() and getTankOfResidence() are instance methods because they access non-static variables.

  • fishTank() is a static method and accesses a static variable (numTanks).

  • Another use of static methods is for creating class instances when the class constructor access is private.

  • This is possible because the static method is publicly accessible with private access to the class.

  • Example:

    // some code here
    private Nesting() {
        // implementation
    }
    
    // some code here
    public static Nesting getInstance() {
        Nesting nesting = new Nesting();
        return nesting;
    }
    
    // some code here
    // Instantiate a private class with a method.
    Nesting n1 = Nesting.getInstance();
    // some code here
    

Static Nested Classes

  • A nested class is a class created inside another class.

  • Static classes can exist as nested classes and cannot exist as independent classes.

  • Static nested classes:

    • Are implemented inside other classes (container classes).
    • Can extend the behavior of the container class.
    • Can be overloaded like ordinary constructors.
  • The static nested class provides a means for instantiating a containing class when its constructor has private access.

  • This is another way to instantiate a class with a restricted or private access qualifier for its class constructors.

  • Example:

    public class Space {
        // Space class variables
        public static class Planet {
            // Planet class variables and constructors
            public Planet() {
                // implementation
            }
        public Planet(String, int size) {
            // implementation
        }
    }
    // more Space class implementation
    
    }