views:

234

answers:

6

Hi

public class TestClass
{
    public static void main(String[] args) 
    {
        TestClass t = new TestClass();
    }

    private static void testMethod(){
        abstract class TestMethod{
            int a;
            int b;
            int c;

            abstract void implementMe();
        }

        class DummyClass extends TestMethod{
            void implementMe(){

            }
        }

        DummyClass dummy = new DummyClass();
    }
}

I found out that the above piece of code is perfectly legal in Java. I have the following questions.

  1. What is the use of ever having a class definition inside a method?
  2. Will a class file be generated for DummyClass
  3. Its hard for me to imagine this concept in an Object Oriented manner. Having a class definition inside a behavior. Probably can someone tell me with equivalent real world examples.
  4. Abstract classes inside a method sounds a bit crazy to me. But no interfaces allowed. Is there any reason behind this?

Thanks

Edit: Added one more question regarding Abstract method classes.

+3  A: 
  1. The class can't be seen (i.e. instantiated, its methods accessed without Reflection) from outside the method. Also, it can access the local variables defined in testMethod(), but before the class definition.

  2. I actually thought: "No such file will be written." until I just tried it: Oh yes, such a file is created! It will be called something like A$1B.class, where A is the outer class, and B is the local class.

  3. Especially for callback functions (event handlers in GUIs, like onClick() when a Button is clicked etc.), it's quite usual to use "anonymous classes" - first of all because you can end up with a lot of them. But sometimes anonymous classes aren't good enough - especially, you can't define a constructor on them. In these cases, these method local classes can be a good alternative.

Chris Lercher
2. Ehrm, sure it will. Class files will be generated for every nested, local or anonymous class in your java file.
sepp2k
"2. No such file will be written." -- this is wrong. It creates `TestClass$1TestMethodClass.class`, analogous to how inner classes `.class` files are named.
polygenelubricants
Good answer, exception for 2: you will get the anonymous class generated, in this case "TestClass$1TestMethodClass.class"
Steve B.
Yes, I'm sorry! I didn't realize this until a few seconds ago. You live and learn :-))
Chris Lercher
+3  A: 

Those are called local classes. You can find a detailed explanation and an example here. The example returns a specific implementation which we doesn't need to know about outside the method.

BalusC
+1  A: 

The real purpose of this is to allow us to create classes inline in function calls to console those of us who like to pretend that we're writing in a functional language ;)

Steve B.
+2  A: 

This is called a local class.

2 is the easy one: yes, a class file will be generated.

1 and 3 are kind of the same question. You would use a local class where you never need to instantiate one or know about implementation details anywhere but in one method.

A typical use would be to create a throw-away implementation of some interface. For example you'll often see something like this:

  //within some method
  taskExecutor.execute( new Runnable() {
       public void run() {
            classWithMethodToFire.doSomething( parameter );
       }
  }); 

If you needed to create a bunch of these and do something with them, you might change this to

  //within some method
  class myFirstRunnableClass implements Runnable() {
       public void run() {
            classWithMethodToFire.doSomething( parameter );
       }
  }
  class mySecondRunnableClass implements Runnable() {
       public void run() {
            classWithMethodToFire.doSomethingElse( parameter );
       }
  }
  taskExecutor.execute(new myFirstRunnableClass());
  taskExecutor.execute(new mySecondRunnableClass());

Regarding interfaces: I'm not sure if there's a technical issue that makes locally-defined interfaces a problem for the compiler, but even if there isn't, they wouldn't add any value. If a local class that implements a local interface were used outside the method, the interface would be meaningless. And if a local class was only going to be used inside the method, both the interface and the class would be implemented within that method, so the interface definition would be redundant.

JacobM
Thanks! What about question 4?
Bragboy
Edited to add discussion of interfaces.
JacobM
+1  A: 

The main reason to define inner classes (within a method or a class) is to deal with accessibility of members and variables of the enclosing class and method. An inner class can look up private data members and operate on them. If within a method it can deal with final local variable as well.

Having inner classes does help in making sure this class is not accessible to outside world. This holds true especially for cases of UI programming in GWT or GXT etc where JS generating code is written in java and behavior for each button or event has to be defined by creating anonymous classes

Fazal
+1  A: 

The only case when you would like to have a full blown function inner class vs anonymous class ( a.k.a. Java closure ) is when the following conditions are met

  1. you need to supply an interface or abstract class implementation
  2. you want to use some final parameters defined in calling function
  3. you need to record some state of execution of the interface call.

E.g. somebody wants a Runnable and you want to record when the execution has started and ended.

With anonymous class it is not possible to do, with inner class you can do this.

Here is an example do demonstrate my point

private static void testMethod (
        final Object param1,
        final Object param2
    )
{
    class RunnableWithStartAndEnd extends Runnable{
        Date start;
        Date end;

        public void run () {
            start = new Date( );
            try
            {
                evalParam1( param1 );
                evalParam2( param2 );
                ...
            }
            finally
            {
                end = new Date( );
            }
        }
    }

    final RunnableWithStartAndEnd runnable = new RunnableWithStartAndEnd( );

    final Thread thread = new Thread( runnable );
    thread.start( );
    thread.join( );

    System.out.println( runnable.start );
    System.out.println( runnable.end );
}

Before using this pattern though, please evaluate if plain old top-level class, or inner class, or static inner class are better alternatives.

Alexander Pogrebnyak