Use of class definitions inside a method in Java

JavaClassLocal Class

Java Problem Overview


Example:

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. It's 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?

Java Solutions


Solution 1 - Java

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.

Solution 2 - Java

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.

Solution 3 - Java

  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.

Solution 4 - Java

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 ;)

Solution 5 - Java

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.

Solution 6 - Java

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

Solution 7 - Java

I've came across a good example in the Spring. The framework is using concept of local class definitions inside of the method to deal with various database operations in a uniform way.

Assume you have a code like this:

JdbcTemplate jdbcOperations = new JdbcTemplate(this.myDataSource);
jdbcOperations.execute("call my_stored_procedure()")
jdbcOperations.query(queryToRun, new MyCustomRowMapper(), withInputParams);
jdbcOperations.update(queryToRun, withInputParams);

Let's first look at the implementation of the execute():

    @Override
	public void execute(final String sql) throws DataAccessException {
		if (logger.isDebugEnabled()) {
			logger.debug("Executing SQL statement [" + sql + "]");
		}

		/**
		 * Callback to execute the statement.
         (can access method local state like sql input parameter)
		 */
    	class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider {
    		@Override
    		@Nullable
    		public Object doInStatement(Statement stmt) throws SQLException {
    			stmt.execute(sql);
    			return null;
    		}
    		@Override
    		public String getSql() {
    			return sql;
    		}
    	}

        //transforms method input into a functional Object
    	execute(new ExecuteStatementCallback());
    }

Please note the last line. Spring does this exact "trick" for the rest of the methods as well:

//uses local class QueryStatementCallback implements StatementCallback<T>, SqlProvider
jdbcOperations.query(...) 
//uses local class UpdateStatementCallback implements StatementCallback<Integer>, SqlProvider
jdbcOperations.update(...)

The "trick" with local classes allows the framework to deal with all of those scenarios in a single method which accept those classes via StatementCallback interface. This single method acts as a bridge between actions (execute, update) and common operations around them (e.g execution, connection management, error translation and dbms console output)

public <T> T execute(StatementCallback<T> action) throws DataAccessException    {
		Assert.notNull(action, "Callback object must not be null");

		Connection con = DataSourceUtils.getConnection(obtainDataSource());
		Statement stmt = null;
		try {
			stmt = con.createStatement();
			applyStatementSettings(stmt);
            //
			T result = action.doInStatement(stmt);
			handleWarnings(stmt);
			return result;
		}
		catch (SQLException ex) {
			// Release Connection early, to avoid potential connection pool deadlock
			// in the case when the exception translator hasn't been initialized yet.
			String sql = getSql(action);
			JdbcUtils.closeStatement(stmt);
			stmt = null;
			DataSourceUtils.releaseConnection(con, getDataSource());
			con = null;
			throw translateException("StatementCallback", sql, ex);
		}
		finally {
			JdbcUtils.closeStatement(stmt);
			DataSourceUtils.releaseConnection(con, getDataSource());
		}
	}

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
QuestionbragboyView Question on Stackoverflow
Solution 1 - JavaJacob MattisonView Answer on Stackoverflow
Solution 2 - JavaBalusCView Answer on Stackoverflow
Solution 3 - JavaChris LercherView Answer on Stackoverflow
Solution 4 - JavaSteve B.View Answer on Stackoverflow
Solution 5 - JavaAlexander PogrebnyakView Answer on Stackoverflow
Solution 6 - JavaFazalView Answer on Stackoverflow
Solution 7 - Javas-evgheniView Answer on Stackoverflow