Does Java support inner / local / sub methods?

JavaMethods

Java Problem Overview


This is my code.

public class SubFunction {
	private String drawTribleX(){
		return trible("X");
	}
	private String trible(String t){
		return t + t + t;
	}
	public static void main(String[] args){
		SubFunction o = new SubFunction();
		System.out.println(o.drawTribleX());
	}
}

Can I do something like this ?

public class SubFunction {
	private String drawTribleX(){
		// *** move trible(t) inside drawTribleX() ***
		private String trible(String t){
			return t + t + t;
		}
		return trible("X");
	}
	public static void main(String[] args){
		SubFunction o = new SubFunction();
		System.out.println(o.drawTribleX());
	}
}

Thank you.

Java Solutions


Solution 1 - Java

Update 2014-02-09:

JDK 8 introduced lambdas (anonymous function expressions) which allow you to solve it like this:

Function<String, String> trible = s -> s+s+s;
System.out.println(trible.apply("X"));           // prints XXX

(JDK 7 and below)

No, Java does not support "directly" nested methods. (Most functional languages do though, including some JVM languages such as Scala and Clojure!)

Just for reference though; You can define local classes (classes within methods) so this does compile

class SubFunction {
    private String drawTribleX(){

        // *** move trible(t) inside drawTribleX() ***
        class Trible {
            private String trible(String t){
                return t + t + t;
            }
        }

        return new Trible().trible("X");
    }
    public static void main(String[] args){
        SubFunction o = new SubFunction();
        System.out.println(o.drawTribleX());
    }
}

Note though that there are some restrictions on local classes

> 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.

So, as you can see, your first option (without nested methods) is preferable in these situations.

Solution 2 - Java

Quite simply - no. You can't nest a method within another method.

If you really want to do this, you can define classes within methods (strangely, given the previous restriction) and so could wrap your methods within a class within the outer method.

However, this isn't very idiomatic, and the general practice seems to be to have a list of private methods (in the top level class), perhaps grouped according to purpose and with comment blocks demarcating the groups.


If you happen to find yourself using Scala, however, you can nest methods away to your heart's content...

Solution 3 - Java

you can try in this way as well which is anonymous inner class.

public class SubFunction {
	private String drawTribleX() {
		// *** move trible(t) inside drawTribleX() ***
		Trible t = new Trible() {
			public String trible(String t) {
				return t + t + t;
			}
		};
		return t.trible("X");
	}

	public static void main(String[] args) {
		SubFunction o = new SubFunction();
		System.out.println(o.drawTribleX());
	}

	interface Trible {
		String trible(String t);
	}
}

Solution 4 - Java

You could use an anonymous class. Something like this;

class SubFunction {

    public static void main(String[] args) {
        SubFunction o = new SubFunction();
        System.out.println(o.drawTribleX());
    }

    private String drawTribleX() {
        MyTrible trible = new MyTrible() {
            @Override
            public String doTrible(String t) {
                return t + t + t;
            }
        };

        return trible.doTrible("X");
    }

    private interface MyTrible {
        public String doTrible(String t);
    }
}

If you wanted you could define different types of operations with the same interface, and pass these around as you like.

Solution 5 - Java

It is possible to write lambdas inside any method.

Using lambda for example to create a recursive method:

Expecting an object like

class Foo{
   Foo parent;
}

Interface for the lambda method expression

public interface Function<ARGUMENTTYPE, RETURNTYPE>{
    RETURNTYPE apply(ARGUMENTTYPE argument);
}

Recursive findRoot method to get the top level Foo.parent

private Foo findRoot(final Foo foo) {
    //Create a Lambda Function for recursive search.
    final Function<Foo, Foo> recursiveSearch = new Function<Foo, Foo>() {
        @Override
        public Foo apply(final Foo fee) {
            //is the parent null return null
            if (fee.parent == null) {
                return null;
            } else if (fee.parent.equals(fee)) {
                //safety check ;-)
                throw new IllegalStateException("Circular Dependencies of " + fee.toString());
            } else {
                Foo parentFoo = fee.parent;
                //check if parent has parent otherwise return parent in else block
                if (parentFoo != null && parentFoo.parent != null) {
                    return this.apply(parentFoo);
                } else {
                    return parentMarket;
                }
            }
        }
    };
    //get the root
    final Foo rootFoo = recursiveSearch.apply(foo);
    //Safety check 2 ;-)
    if (rootFoo != null && rootFoo.equals(foo)) {
        throw new IllegalStateException("Circular Dependencies of " + foo.toString)();
    }
    return rootFoo;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondiewlandView Question on Stackoverflow
Solution 1 - JavaaioobeView Answer on Stackoverflow
Solution 2 - JavaAndrzej DoyleView Answer on Stackoverflow
Solution 3 - JavaGuruKulkiView Answer on Stackoverflow
Solution 4 - Javafirefox1986View Answer on Stackoverflow
Solution 5 - JavaPwnstarView Answer on Stackoverflow