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