Java: Local methods (or submethods, or inner methods, or nested methods)

Java does not support local methods. This will not compile:

class C {
    void m() {
        void n() {
            System.out.println("Hello World");
        }
        n();
    }
}

Here are a few alternatives that do compile…

Using a lambda (Java 8+)

class C {
    void m() {
        Runnable r = () -> {
            System.out.println("Hello World");
        };
        r.run();
    }
}

You may also access local variables, pass arguments and read return values:

import java.io.PrintStream;
import java.util.function.Function;
class C {
    void m() {
        PrintStream pw = System.out;
        Function<String, Integer> print = str -> {
            pw.println(str);
            return str.length();
        };
        int charsPrinted = print.apply("Hello World");
    }
}

See also: Lambda Cheat Sheet

Using anonymous subclasses

Slightly more verbose than the above, but works in Java 7 and below.

class C {
    void m() {
        Runnable r = new Runnable() {
            public void run() {
                System.out.println("Hello World");
            };
        };
        r.run();
    }
}

Using local classes

class C {
    void m() {
        class Local {
            void n() {
                System.out.println("Hello World");
            }
        }
        new Local().n();
    }
}

Note that local classes comes with some restrictions:

3.11.2. Restrictions on Local Classes

Local classes are subject to the following restrictions:

  • A local class is visible only within the block that defines it; it can never be used outside that block.

  • Local classes cannot be declared public, protected, private, or static. These modifiers are for members of classes; they are not allowed with local variable declarations or local class declarations.

  • Like member classes, and for the same reasons, local classes cannot contain static fields, methods, or classes. The only exception is for constants that are declared both static and final.

  • Interfaces cannot be defined locally.

  • A local class, like a member class, cannot have the same name as any of its enclosing classes.

  • As noted earlier, a local class can use the local variables, method parameters, and even exception parameters that are in its scope, but only if those variables or parameters are declared final. This is because the lifetime of an instance of a local class can be much longer than the execution of the method in which the class is defined. For this reason, a local class must have a private internal copy of all local variables it uses (these copies are automatically generated by the compiler). The only way to ensure that the local variable and the private copy are always the same is to insist that the local variable is final. Java in a Nutshell, Chapter 3.11.2

Local Scoping

If all you're after is localized scoping, you can simply do:

class C {
    void m() {
        {
            int i = 7;
            System.out.println(i);
        }
        // System.out.println(i);  Wouldn't compile. i is out of scope.
    }
}

Comments

Be the first to comment!