Java Local inner class

A local inner class in Java is a class that is defined inside a method or a block of code. It is a nested class that can only be accessed within the scope of the method or block in which it is defined.

Local inner classes have access to the variables and parameters of the method or block in which they are defined. They can also access instance variables and methods of the enclosing class.

Here is an example of a local inner class:

public class OuterClass {
   public void method() {
      final int x = 10; // local variable
      class InnerClass {
         public void printX() {
            System.out.println(x); // access local variable of enclosing method
         }
      }
      InnerClass inner = new InnerClass();
      inner.printX();
   }
}

In this example, the InnerClass is defined inside the method() of the OuterClass. It can access the local variable x declared in method(). An instance of InnerClass is created and its method printX() is called to print the value of x.

Local inner classes are useful when you need to define a class that is only used in one method or block of code. They can help to keep your code organized and can improve encapsulation by hiding implementation details of the enclosing class.

Internal class generated by the compiler:

In Java, when you define a class that is marked as private, protected, or has default (package) access, the compiler will automatically generate an internal class with a name that consists of the outer class’s name followed by a $ and a number.

This internal class is used to provide access to the private, protected, or default members of the outer class from within other classes in the same package. It is also used to implement inner classes, anonymous classes, and lambda expressions.

For example, consider the following code:

public class Outer {
    private int x;
    protected int y;
    int z;
    
    private class Inner {
        public void doSomething() {
            x = 1;
            y = 2;
            z = 3;
        }
    }
}

In this code, Outer has a private inner class Inner. The compiler will generate an internal class named Outer$Inner to represent this inner class. This internal class will have access to the private member x, the protected member y, and the default member z of the outer class.

You can see the generated internal class file by compiling the code and looking at the .class files that are generated. For example, if you compile the above code with javac Outer.java, you will see that the compiler has generated a file named Outer$Inner.class, which represents the internal class generated for the Inner class.

Rules for Java Local Inner class:

In Java, there are a few rules for defining local inner classes:

  1. Local inner classes can only be defined inside a block of code, such as a method or a static initializer block.
  2. Local inner classes can access the variables and parameters of the enclosing method or block of code, but only if they are declared final or effectively final.
  3. Local inner classes can access instance variables and methods of the enclosing class, as well as static variables and methods of the enclosing class.
  4. Local inner classes can have access modifiers, such as public, private, protected, or default (package) access.
  5. Local inner classes cannot have static members, except for final static constants.
  6. Local inner classes cannot have constructors, except for anonymous inner classes.
  7. Local inner classes can implement interfaces or extend classes, just like any other class.
  8. Local inner classes can have inner classes of their own, but these inner classes cannot be accessed from outside the local inner class.

Here is an example that illustrates some of these rules:

public class Outer {
    private int x = 10;
    public void doSomething() {
        final int y = 20;
        class Inner {
            private int z = 30;
            public void print() {
                System.out.println("x = " + x); // access instance variable of enclosing class
                System.out.println("y = " + y); // access local variable of enclosing method
                System.out.println("z = " + z); // access inner class variable
            }
        }
        Inner inner = new Inner();
        inner.print();
    }
}

In this example, Outer defines a local inner class Inner inside the doSomething() method. The Inner class can access the instance variable x of the Outer class, as well as the local variable y of the doSomething() method. The Inner class also defines its own instance variable z, which can only be accessed within the Inner class.

Note that the y variable is declared final, which is required in order to access it from within the Inner class. Also note that the Inner class has no access modifiers, which means it has default (package) access.

Example of local inner class with local variable:

Here is an example of a local inner class in Java that accesses a local variable of its enclosing method:

public class OuterClass {
   public void method() {
      final int x = 10; // local variable
      class InnerClass {
         public void printX() {
            System.out.println(x); // access local variable of enclosing method
         }
      }
      InnerClass inner = new InnerClass();
      inner.printX();
   }
}

In this example, the InnerClass is defined inside the method() of the OuterClass. It can access the local variable x declared in method(). The x variable is marked as final, which means that its value cannot be changed after it is initialized.

An instance of InnerClass is created and its method printX() is called to print the value of x. The output of the program would be:

10

because printX() accesses the value of x which is set to 10.