Nested Classes

Instance Variables:

  • When multiple objects are created from the same class blueprint, each instance contains its own distinct copies of instance variables.

    • These instances maintain unique states for each object, ensuring encapsulation.

    • Changes to an instance variable in one object do not affect the same variable in another object.

  • Example: In a Bicycle class with instance variables such as cadence, gear, and speed, different instances can hold unique values for these properties.

    • Code Example:
      java public class Bicycle { private int cadence; // Current cadence of the bicycle private int gear; // Gear the bicycle is using private int speed; // Current speed of the bicycle private int id; // Unique object ID }

  • The id instance variable allows multiple Bicycle objects to be uniquely identified while sharing the same methods and flexibility.

Class Members:

  • Static Variables:

    • Common variables shared across all instances of a class.

    • Stored in a fixed memory location and exist independently from specific objects, making them efficient for class-wide data.

    • Example: A static variable can track the total number of instantiated Bicycle objects.

    • Code Example:

    public class Bicycle {
        private static int numberOfBicycles = 0; // Shared across instances
    }
    
  • Static Methods:

    • Declared with the static keyword and can be invoked without creating class instances.

    • Operate only on static variables, promoting utility functions related to the class.

    • Example: A static method can return the total created Bicycle instances using the static variable.

    • Code Example:

    public static int getNumberOfBicycles() {
        return numberOfBicycles; // Returns count of Bicycle instances
    }
    
  • Class Methods:

    • Access rules dictate method interactions with class and instance variables.

    • Instance methods can access both instance and class variables/methods, while class methods can only access static ones.

    • Class methods cannot access instance variables directly due to lack of an object context and require an object reference for access.

Nested Classes:

  • Definition:

    • A class defined within another class to enhance encapsulation and logical structure.

    • Helps with the organization of related functionality in larger applications.

    • Results in two separate class files upon compilation: OuterClass.class for the outer and OuterClass$InnerClass.class for the nested class.

  • Types of Nested Classes:

    • Static Nested Classes:

    • Access static members of the outer class but not instance members.

    • Can be instantiated independently of outer class instances.

    • Example Syntax: OuterClassName.NestedClassName.methodName();

      • Code Example:

      class Outer {
          static class Nested {
              // Implementation
          }
      }
    
    • Inner Classes:

    • Tied to an instance of the enclosing class, gaining access to all members (including private ones).

    • Instantiate using an instance of the outer class, fostering deep integration between classes.

    • Code Example:

      OuterClass outerObject = new OuterClass();
      OuterClass.InnerClass innerObject = outerObject.new InnerClass();
    
  • Private Members Access:

    • Inner classes can access private members of the outer class, enhancing encapsulation.

    • Outer classes access non-static members through an instance of the inner class.

    • Example: A BankAccount class with a Money inner class can demonstrate secure manipulation of private data.

Benefits of Nested Classes:

  • Logical grouping of related classes simplifies functionality access.

  • Enhances encapsulation, guarding implementation details from external interference.

  • Improves code readability and maintainability, ensuring related functionalities remain together.

  • Useful for creating helper classes limited to one outer class, reducing namespace clutter.

Shadowing in Nested Classes:

  • If a variable in a nested class shares the same name as a variable in the outer class, it shadows the outer variable.

  • This ambiguity can cause issues if not managed properly.

    • Example demonstrating shadowing:

    public class ShadowTest {
        public int x = 0; // Outer class variable
        class FirstLevel {
            public int x = 1; // Inner class variable
            void methodInFirstLevel(int x) { // Parameter named x
                System.out.println("x = " + x); // Refers to parameter
                System.out.println("this.x = " + this.x); // Refers to inner class x
                System.out.println("ShadowTest.this.x = " + ShadowTest.this.x); // Refers to outer class x
            }
        }
    }
    
  • Anonymous Classes:

    • Allow declaring and instantiating classes at the same time, suitable for non-reusable implementations (e.g., event handlers).

    • Syntax:

    ClassName obj = new ClassName() { 
        // class body
    };
    
    • Can capture and use local variables from their context, requiring final or effectively final variable declarations.

  • Local Classes:

    • Defined within a method, can access final or effectively final local variables.

    • Cannot declare static members, as their lifecycle is tied to the enclosing method.

    • Example of using a local class to validate phone numbers:
      java public static void validatePhoneNumber(String phoneNumber) { class PhoneNumber { // PhoneNumber class implementation } }

Clicker Questions:

  • Designed to assess understanding of nested classes and their characteristics, providing scenarios concerning:

    • Instantiation

    • Access rules

    • Interaction between inner