67

Are there any extensions for the Java programming language that make it possible to create nested functions?

There are many situations where I need to create methods that are only used once in the context of another method or for-loop. I've been unable to accomplish this in Java so far, even though it can be done easily in JavaScript.

For example, this can't be done in standard Java:

for(int i = 1; i < 100; i++){
    times(2); // Multiply i by 2 and print i
    times(i); // Square i and then print the result

    public void times(int num){

        i *= num;
        System.out.println(i);
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Anderson Green
  • 30,230
  • 67
  • 195
  • 328

8 Answers8

77

Java 8 introduces lambdas.

java.util.function.BiConsumer<Integer, Integer> times = (i, num) -> {
    i *= num;
    System.out.println(i);
};
for (int i = 1; i < 100; i++) {
    times.accept(i, 2); //multiply i by 2 and print i
    times.accept(i, i); //square i and then print the result
}

The () -> syntax works on any interface that defines exactly one method. So you can use it with Runnable but it doesn't work with List.

BiConsumer is one of many functional interfaces provided by java.util.function.

It's worth noting that under the hood, this defines an anonymous class and instantiates it. times is a reference to the instance.

Neal Ehardt
  • 10,334
  • 9
  • 41
  • 51
  • This needs to be incorporated somehow into the top answer as this is now the idiomatic solution in my opinion. Interesting how it's implemented with an inner class declaration though. – Kamuela Franco Dec 09 '15 at 07:26
  • 1
    Note: this java program doesn't do the same as the javascript program. I am not sure it was intentional, but the javascript `times` accesses and modifies i. The output is 2, 4, 10, 100. In Java you can access only final variables, that means you cannot modify them. – Florian F Apr 17 '16 at 13:10
  • @FlorianF: Quite right. Lambdas cannot modify their scope. Local variables referenced must be final or "effectively final". More here http://stackoverflow.com/questions/25055392/lambdas-local-variables-need-final-instance-variables-dont – Neal Ehardt Apr 17 '16 at 18:40
  • 1
    Maybe I misunderstood *Java in a Nutshell* that the `() ->` syntax works on any "single abstract method (SAM)" interface, like maybe `Comparator` which defines `compare()` as abstract but gives default implementations for the others, like `reverse()`. – Alonso del Arte Jul 30 '20 at 20:50
31

The answer below is talking about the closest you can get to having nested functions in Java before Java 8. It's not necessarily the way I'd handle the same tasks which might be handled with nested functions in JavaScript. Often a private helper method will do just as well - possibly even a private helper type, which you create an instance of within the method, but which is available to all methods.

In Java 8 of course, there are lambda expressions which are a much simpler solution.


The closest you can easily come is with an anonymous inner class. That's as close as Java comes to closures at the moment, although hopefully there'll be more support in Java 8.

Anonymous inner classes have various limitations - they're obviously rather wordy compared with your JavaScript example (or anything using lambdas) and their access to the enclosing environment is limited to final variables.

So to (horribly) pervert your example:

interface Foo {
    void bar(int x);
}

public class Test {
    public static void main(String[] args) {
        // Hack to give us a mutable variable we can
        // change from the closure.
        final int[] mutableWrapper = { 0 };

        Foo times = new Foo() {
            @Override public void bar(int num) {
                mutableWrapper[0] *= num;
                System.out.println(mutableWrapper[0]);
            }
        };

        for (int i = 1; i < 100; i++) {
            mutableWrapper[0] = i;
            times.bar(2);
            i = mutableWrapper[0];

            times.bar(i);
            i = mutableWrapper[0];
        }
    }
}

Output:

2
4
10
100

Is that the output you get from the JavaScript code?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Anonymous inner class? Really? I'd say the idiomatic way is to just use a `private` helper method... – Matt Ball Sep 09 '11 at 21:42
  • @Matt: How do you declare that within another method though? I'm not saying I wouldn't use private helper methods - I'm saying they're not nested functions. Will edit to talk about this though. – Jon Skeet Sep 09 '11 at 21:45
  • 12
    The only problem with private helper methods (as opposed to inner functions) is that they add clutter to the source code by making functions available outside their intended scope. – Anderson Green Sep 09 '11 at 22:27
  • 15
    @Andy: Well, not just that - they don't have access to the variables in the method you're interested in, whereas nested functions do. Closures can be incredibly handy... – Jon Skeet Sep 09 '11 at 22:29
29

I think that the closest you can get to having nested functions in Java 7 is not by using an anonymous inner class (Jon Skeet's answer), but by using the otherwise very rarely used local classes. This way, not even the interface of the nested class is visible outside its intended scope and it's a little less wordy too.

Jon Skeet's example implemented with a local class would look as follows:

public class Test {
    public static void main(String[] args) {
        // Hack to give us a mutable variable we can
        // change from the closure.
        final int[] mutableWrapper = { 0 };

        class Foo {
            public void bar(int num) {
                mutableWrapper[0] *= num;
                System.out.println(mutableWrapper[0]);
            }
        };

        Foo times = new Foo();

        for (int i = 1; i < 100; i++) {
            mutableWrapper[0] = i;
            times.bar(2);
            i = mutableWrapper[0];

            times.bar(i);
            i = mutableWrapper[0];
        }
    }
}

Output:

2
4
10
100
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
deinocheirus
  • 1,833
  • 5
  • 26
  • 44
2

For non-argument method you can create Runnable object

private static void methodInsideMethod(){
    Runnable runnable = new Runnable(){
        @Override
        public void run(){
            System.out.println("Execute something");
        }
    };

    for(int i = 0; i < 10; i++){
        runnable.run();
    }
}
NM Naufaldo
  • 1,032
  • 1
  • 12
  • 30
2

Such methods are sometimes called closures. Have a look at Groovy – perhaps you will prefer it to Java. In Java 8 there will probably be closures as well (see JSR335 and deferred list).

DaveFar
  • 7,078
  • 4
  • 50
  • 90
dma_k
  • 10,431
  • 16
  • 76
  • 128
  • I guess it's a little late for Java 7 to have closures :) – yozh Sep 09 '11 at 21:46
  • I agree (checked [here](http://openjdk.java.net/projects/lambda/)) :) There were so many expectations raised. – dma_k Sep 09 '11 at 21:51
  • What can be done about this problem, then? Someone could probably write a pre-processor for Java to "simulate" this, but that's just slightly above my skill level. – Anderson Green Sep 09 '11 at 22:21
1

I don't know if anyone else has figured this out, but apparently you can do magic with the var keyword that comes with Java 10 and above. This saves you from having to declare an interface if you don't have one that will work for you.

public class MyClass {
    public static void main(String args[]) {
        var magic = new Object(){
            public void magic(){
                System.out.println("Hello World!");
            }
        };
        magic.magic();
    }
}

I have tested it and it works. I haven't found a Java compiler that lets you do a simple share yet.

BrainStorm.exe
  • 1,565
  • 3
  • 23
  • 40
0

Consider making an anonymous local class and using its initializer block to do the work:

public class LocalFunctionExample {
    public static void main(final String[] args) {
        for (final int i[] = new int[] { 1 }; i[0] < 100; i[0]++) {
            new Object() {
                {
                    times(2); //multiply i by 2 and print i
                    times(i[0]); //square i and then print the result
                }

                public void times(final int num) {
                    i[0] *= num;
                    System.out.println(i[0]);
                }
            };
        }
    }
}

Output:

2
4
10
100

(The "final wrapper trick" is not automatically required with this technique, but was needed here to handle the mutation requirement.)

This works out to be almost as concise as the lambda version, but you get to use whatever method signatures you want, they get to have real parameter names, and the methods are called directly by their names - no need to .apply() or whatnot. (This kind of thing sometimes makes IDE tooling work a little better too.)

Woody Zenfell III
  • 1,905
  • 17
  • 31
-9

I hate to use the forbidden word but you could use a goto statement to create an an effective subroutine inside the method. It is ugly and dangerous but much easier than what was shown in previous answers. Although the private method with a call inside of the first method is much better, and serves you needs just fine. I don't know why you would want to use a nested method for something as simple as this.

Michael Bray
  • 14,998
  • 7
  • 42
  • 68