Nested Anonymous Inner ClassesJ8 Home « Nested Anonymous Inner Classes

In the Nested Inner Classes lesson we took our first look at inner classes as we learned about the various ways to code inner classes and local inner classes within our classes. In this final lesson on nested classes we look at the different anonymous inner classes and how to code them.

.

Anonymous Inner Classes Top

The final type of inner classes we can use are anonymous inner classes which are different syntactically from anything else in Java and come with a lot of constraints:

  • Anonymous inner classes as the terminology implies have no name.
  • You can't execute the instanceof test against anonymous inner classes or any process that requires the name of the class.
  • Anonymous inner classes are not members of their enclosing class; in fact they are both declared and instantiated at the point of use.
  • Anonymous inner classes cannot contain any static members
  • Anonymous inner classes can be coded anywhere where an expression is legal, so keep the code to a minimum to maintain readability.
  • Anonymous inner classes can't be declared to extend a class and implement an interface
  • Anonymous inner classes can't implement multiple interfaces.
  • Anonymous inner classes can only invoke members inherited from the supertype

Subclass Example Top

Following is an example of using an anonymous inner class to override a method of the supertype.


package info.java8;
/*
  A Top-level Class
*/ 
public class OuterAnon {
    
    public void aMethod() {
        System.out.println("Outer method"); 
    }
    public void anonymousSubclass() {
        /*
          Anonymous inner class
        */ 
        OuterAnon  outerAnon = new OuterAnon() {
            public void aMethod() {
                System.out.println("anonymous method"); 
            }
        }; // Here we close the anonymous inner class
        outerAnon.aMethod();
    }
}

The first thing to notice about the above code is that instead of ending the OuterAnon outerAnon = new OuterAnon() statement with a semi-colon we are actually writing a code block. What we are actually doing here is declaring a reference type of the OuterAnon supertype that doesn't refer to an instance of OuterAnon but to an anonymous subclass of it. All the override code for the supertype aMethod(), for our 'on the fly' subclass instance is held within the code block which is then followed by a semi-colon. In essence we are closing the OuterAnon outerAnon = new OuterAnon() statement with the semi-colon after doing whatever is required in our code block.

Save and compile the file in directory   c:\_ObjectsAndClasses in the usual way.

Lets write a new test class for our OuterAnon class.


package info.java8;
/*
  Test Class for OuterAnon
*/ 
public class OuterAnonTest {

    public static void main (String[] args) {
        OuterAnon outerAnon = new OuterAnon();
        outerAnon.aMethod();
        outerAnon.anonymousSubclass();
    }
}

Save, compile and run the file in directory   c:\_ObjectsAndClasses in the usual way.

run outer anon test

The above screenshot shows the output of running our OuterAnonTest class. We create an outer class instance and call the aMethod() and output a message. We then call the anonymousSubclass() method where our anonymous inner class is declared and instantiated. Within this we override the supertype aMethod() method and output a message.

Implementer Example Top

We can also use anonymous inner classes as implementers of an interface. Following is the code for the PublicTransport interface we used in the last lesson:


package info.java8;
/*
 The PublicTransport interface
*/ 
public interface PublicTransport {

    void queue(int queue);  // The public and abstract modifiers are added by the compiler
    void payFare(int money);  // The public and abstract modifiers are added by the compiler
}

Following is an example of using an anonymous inner class to declare and instantiate an implementer of the PublicTransport interface 'on the fly' whilst honouring the contract of the interface.


package info.java8;
/*
  A Top-level Class
*/ 
public class OuterAnon2 {
    public void anonymousImplementer() {
        /*
          Anonymous inner class
        */ 
        PublicTransport pt = new PublicTransport () {
             // Our queue() implementation
             public void queue(int people) {
                 System.out.println("There are " + people + " people waiting at the taxi rank.");
        
             }
             // Our payFare() implementation
             public void payFare(int fare) {
                 System.out.println("This taxi ride will cost you " + fare + " pounds.");
             }
         }; // Here we close the anonymous inner class
         pt.queue(12);
         pt.payFare(3);
    }
}

Well this looks very strange it looks like we are instantiating an interface with the first line of our inner class PublicTransport pt = new PublicTransport(). But we know we can't instantiate an interface as it's like a 100% abstract class, so what is going on? Well what we are actually doing here is declaring a reference type of the PublicTransport interface supertype that refers to an anonymous implementer of the PublicTransport interface. The implementer gets instantiated with the the expression new PublicTransport(). All the implementation code for our new object is held within our code block which is then followed by a semi-colon.

Save and compile the file in directory   c:\_ObjectsAndClasses in the usual way.

Lets write a new test class for our OuterAnon2 class.


package info.java8;
/*
  Test Class for OuterAnon2
*/ 
public class OuterAnon2Test {

    public static void main (String[] args) {
        OuterAnon2 outerAnon2 = new OuterAnon2();
        outerAnon2.anonymousImplementer();
    }
}


Save, compile and run the file in directory   c:\_ObjectsAndClasses in the usual way.

run outer anon test

The above screenshot shows the output of running our OuterAnon2Test class. We create an outer class instance and call the anonymousImplementer() method where our anonymous inner class is declared, instantiated and implemented.

Argument Implementer Example Top

In our final example of anonymous inner classes we look at how to pass an 'on the fly' instantiation and implementation of a method using an interface supertype as an argument. Before we go into this lets look at the Carrier class we created for the Polymorphic Interface Arguments section of the Interfaces lesson, as we will use it for the example:


package info.java8;
/*
  A Carrier class
*/ 
public class Carrier {
    private int people;
    private int cost;

    Carrier(int people, int cost) {
        this.people = people;
        this.cost = cost;
    }

    public void travelInfo(PublicTransport pt) {
        pt.queue(people); 
        pt.payFare(cost); 
    }
}

As a refresher the travelInfo(PublicTransport pt) method of the carrier class above, takes a PublicTransport interface supertype as a parameter and outputs some messages for the implemented class. What we want to do is use an anonymous inner class to pass across an instantiation and implementation of the interface supertype as the argument. Following is code to do this:


package info.java8;
/*
  A Top-level Class
*/ 
public class OuterAnon3 {
    public void anonymousArgImplementer() {
        Carrier cr = new Carrier(25, 4);
        /*
          Anonymous inner class
        */ 
        cr.travelInfo(new PublicTransport() {
             // Our queue() implementation
             public void queue(int people) {
                 System.out.println("There are " + people + " people waiting for a bus.");
             }
             // Our payFare() implementation
             public void payFare(int fare) {
                 System.out.println("This bus journey will cost you " + fare + " pounds.");
             }
         }); // Close anonymous inner class and method argument
    }
}

This looks even stranger than the last example so lets go through the code. The first part to look at is the cr.travelInfo( on the first line of the anonymous inner class declaration. Here we are calling the travelInfo() method using a Bus object. This method accepts a parameter of the PublicTransport interface supertype, so we need to pass an instance of that class along with an implementation of the class all within the argument. The new PublicTransport() part is where we create our 'on the fly' instance and the implementation follows within the {...} code block. We then close the anonymous inner class and we also need to close the method argument that contained it, before terminating the statement.

Save and compile the file in directory   c:\_ObjectsAndClasses in the usual way.

Lets write a new test class for our OuterAnon3 class.


package info.java8;
/*
  Test Class for OuterAnon3
*/ 
public class OuterAnon3Test {

    public static void main (String[] args) {
        // Call the cr.travelInfo() method normally
        Carrier cr = new Carrier(10, 2);
        Bus bus = new Bus();
        cr.travelInfo(bus);
        OuterAnon3 outerAnon3 = new OuterAnon3();
        // Call the cr.travelInfo() method anonymously
        outerAnon3.anonymousArgImplementer();
    }
}

Save, compile and run the file in directory   c:\_ObjectsAndClasses in the usual way.

run outer anon test

The above screenshot shows the output of running our OuterAnon3Test class. We use the travelInfo(PublicTransport pt) method of the Carrier class the normal way by passing an instance of an implemented subtype of the PublicTransport interface supertype. We then use an anonymous inner class that creates an 'on the fly' instantiation and implementation of the PublicTransport interface supertype to be passed as the argument to the travelInfo(PublicTransport pt) method.

Related Quiz

OO Concepts Quiz 18 - Nested Anonymous Inner Classes

Lesson 18 Complete

In this lesson we learnt about the various waysto code anonymous inner classes.

What's Next?

In the next lesson we look at the Object object, the daddy of all objects.