Nested functions in Java

I am always looking for ways to increase code clarity and reduce confusion and maintenance associated with “dangling methods”. What’s a dangling method? It’s a method that is only used by another method to reduce code duplication. The scope of this method should therefore be local to only the calling function.

I tend to run into this problem when doing string manipulation. Currently I need to do a “last added character” for a CharBuffer. The only way to currently do this is to add a member function:

private char lastChar(final CharBuffer buffer) {
    // determine if there are already chars in the buffer.  If
    // there are none, throw.
    if(buffer.position <= 0)
        throw new IndexOutOfBoundsException();
    /* else -- there are characters in the buffer */
    // retrieve the last character placed into the buffer
    // NOTE:  the above check ensures that there will be a char
    return buffer.get(buffer.position - 1);
}

to the class. This is no good since the scope of the method is too large. Large scope equals more time determining dependencies which equals more time to debug.

If Java allowed for nested functions, one could write:

private String normalize(final String string)
{
...
// inner function for determining the last character
// added to a buffer
char lastChar(final CharBuffer buffer)
{
...
};
...
case '/':
if(lastChar(buffer) != '/')
...
...
}

Having nested (or inner) functions in Java would help enormously. Kris Wehner brought up a Smalltalk technique which would be somewhat useful in this case. What do you think a solution to this problem would be?

Advertisements

8 comments

  1. Not exactly what you asked for but you can always use an anonymous inner class….
    SomeClass {

    private interface I {
    char lastChar(CharBuffer b);
    }
    private String normalize(…) {
    I i = new I() {
    public char lastChar(…) {
    }
    }
    char c = i.lastChar(…);

    }
    }

  2. You are most certainly correct that an inner class (essentially a command pattern) can be used to simulate what is desired in inner (or nested) functions. But what an inner class doesn’t do for me is *completely* restrict the scope its use (since the interface has a larger scope) and that is what I am after. The more code that I can exclude from testing due to scope the better!

  3. AFAIK, the only way to get rid of the interface I is by doing something like
    Object o = new Object() {
    char lastChar(String s) {

    }
    and use reflection to invoke lastChar() but it is nothing I would recommend šŸ™‚
    Out of curiosity, if nested functions ever gets implemented, would you expect them to have access to local variables in the enclosing function (like anonymous inner classes)?

  4. The reflection call would indeed be ugly!
    I would expect standard scoping rules to apply. So, yes, the inner functions would have access to local variables.
    Thank you for your comments!

  5. It’s been a few years since the last post. I would like to post the use of nested classes for your review.
    private String normalize(final String string)
    {

    class MethodClass {
    char lastChar(final CharBuffer buffer)
    {

    }
    }
    MethodClass myMethodClass = new MethodClass();

    case ‘/’:
    if(myMethodClass.lastChar(buffer) != ‘/’)


    }

  6. What’s funny about what you’ve proposed is that the “class” keyword was not allowed within functions back when I wrote this post otherwise I would have just implemented what you suggested and been a happy man.
    Is this a recent change to the Java Language Specification, something that’s now supported in IDE’s (since I was using Eclipse at the time), or something else completely?
    Thanks for your post!

  7. I’m sorry I can’t answer your question as to when the “class” keyword started being supported. All I can say is I am using the lastest Eclipse IDE with Java 1.5, nothing fancy.
    Thanks.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s