Friday, February 25, 2011

Chapter 54: Anonymous Inner Classes

In the chapter on Inner classes, I had promised that we will look in more detail about the different types of inner classes. Well here we are. In the series of types of specialized inner classes our next stop is “Anonymous” ones.

So far we’ve looked at defining a class within an enclosing class (a regular inner class) and within a method (a method-local inner class). Finally, we’re going to look at the most unusual syntax you might ever see in Java; inner classes declared without any class name at all (probably you figured out why we call it anonymous).

So, lets get started!!!

Anonymous Inner Classes - Type One

Check out the following code:
class Ferrari {
public void drive() {
System.out.println("Ferrari");
}
}
class Car {
Ferrari p = new Ferrari() {
public void drive() {
System.out.println("anonymous Ferrari");
}
};
}

Let’s look at what’s in the preceding code:
• We define two classes, Ferrari and Car.
• Ferrari has one method, drive().
• Car has one instance variable, declared as type Ferrari. That’s it for Car. Car has no methods.

And here’s the big thing to get
The Ferrari reference variable refers not to an instance of Ferrari, but to an instance of an anonymous (unnamed) subclass of Ferrari.

Let’s look at just the anonymous class code:
2. Ferrari p = new Ferrari() {
3. public void drive() {
4. System.out.println("anonymous Ferrari");
5. }
6. };

Line 2

Line 2 starts out as an instance variable declaration of type Ferrari. But instead of looking like this:
Ferrari p = new Ferrari(); // notice the semicolon at the end

there’s a curly brace at the end of line 2, where a semicolon would normally be.
Ferrari p = new Ferrari() { // a curly brace, not a semicolon

You can read line 2 as saying,
Declare a reference variable, p, of type Ferrari. Then declare a new class that has no name, but that is a subclass of Ferrari. And here’s the curly brace that opens the class definition...

Line 3

Line 3, then, is actually the first statement within the new class definition. And what is it doing? Overriding the drive() method of the superclass Ferrari. This is the whole point of making an anonymous inner class—to override one or more methods of the superclass!

Line 4

Line 4 is the first statement within the overriding drive() method. Nothing special here.

Line 5

Line 5 is the closing curly brace of the drive() method. Nothing special here either.

Line 6

Here’s where you have to pay attention: line 6 includes a curly brace closing off the anonymous class definition (it’s the companion brace to the one on line 2), but there’s more! Line 6 also has the semicolon that ends the statement started on line 2—the statement where it all began—the statement declaring and initializing the Ferrari reference variable. And what you’re left with is a Ferrari reference to a brand-new instance of a brand-new, anonymous (no name) subclass of Ferrari.

Exam Tip: The closing semicolon is hard to spot. Watch for code like this:
2. Ferrari p = new Ferrari() {
3. public void drive() {
4. System.out.println("anonymous Ferrari");
5. }
6. } // Missing the semicolon needed to end
// the statement started on 2!
7. Interface1 f = new Interface1();

You’ll need to be especially careful about the syntax when inner classes are involved, because the code on line 6 looks perfectly natural. It’s rare to see semicolons following curly braces.

Anonymous Inner Classes and Polymorphism

Polymorphism is in play when anonymous inner classes are involved. Remember that, as in the preceding Ferrari example, we’re using a superclass reference variable type to refer to a subclass object. What are the implications? You can only call methods on an anonymous inner class reference that are defined in the reference variable type! This is no different from any other polymorphic references, for example,

class McLarenF1 extends F1Car{
void drive() { }
}
class F1Car {
void brake() { }
}
class Test {
public static void main (String[] args) {
F1Car h = new McLarenF1();
h.brake(); // Legal, class F1Car has an brake() method
h.drive(); // Not legal! Class F1Car doesn't have drive()
}
}

So on the exam, you must be able to spot an anonymous inner class that—rather than overriding a method of the superclass—defines its own new method. The method definition isn’t the problem, though; the real issue is how do you invoke that new method? The reference variable type (the superclass) won’t know anything about that new method (defined in the anonymous subclass), so the compiler will complain if you try to invoke any method on an anonymous inner class reference that is not in the superclass class definition.

Check out the following, illegal code:
class Ferrari {
public void drive() {
System.out.println("Ferrari");
}
}

class Car {
Ferrari p = new Ferrari() {
public void brake() {
System.out.println("anonymous sizzling Ferrari");
}
public void drive() {
System.out.println("anonymous Ferrari");
}
};

public void popIt() {
p.drive(); // OK, Ferrari has a drive() method
p.brake(); // Not Legal! Ferrari does not have brake()
}
}

Compiling the preceding code gives us something like,
Anon.java:19: cannot resolve symbol
symbol : method brake()
location: class Ferrari
p.brake();
^


Anonymous Inner Classes Type Two

The only difference between type one and type two is that type one creates an anonymous subclass of the specified class type, whereas type two creates an anonymous implementer of the specified interface type. In the previous examples, we defined a new anonymous subclass of type Ferrari as follows:

Ferrari p = new Ferrari() {

But if Ferrari were an interface type instead of a class type, then the new anonymous class would be an implementer of the interface rather than a subclass of the class. Look at the following example:
interface Drivable {
public void drive();
}
class Car {
Drivable c = new Drivable() {
public void drive() {
System.out.println("anonymous Drivable implementer");
}
};
}

The preceding code, like the Ferrari example, still creates an instance of an anonymous inner class, but this time the new class is an implementer of the Drivable interface. And note that this is the only time you will ever see the syntax

new Drivable()

where Drivable is an interface rather than a non-abstract class type. Because think about it, you can’t instantiate an interface, yet that’s what the code looks like it’s doing. But of course it’s not instantiating a Drivable object, it’s creating an instance of a new, anonymous, implementer of Drivable. You can read this line:

Drivable c = new Drivable() {

as, “Declare a reference variable of type Drivable that, obviously, will refer to an object from a class that implements the Drivable interface. But, oh yes, we don’t yet have a class that implements Drivable, so we’re going to make one right here, right now. We don’t need a name for the class, but it will be a class that implements Drivable, and this curly brace starts the definition of the new implementing class.”

One more thing to keep in mind about anonymous interface implementers—they can implement only one interface. There simply isn’t any mechanism to say that your anonymous inner class is going to implement multiple interfaces. In fact, an anonymous inner class can’t even extend a class and implement an interface at the same time. The inner class has to choose either to be a subclass of a named class—and not directly implement any interfaces at all—or to implement a single interface. By directly, we mean actually using the keyword implements as part of the class declaration. If the anonymous inner class is a subclass of a class type, it automatically becomes an implementer of any interfaces implemented by the superclass.

Exam Tip:
Don’t be fooled by any attempts to instantiate an interface except in the case of an anonymous inner class. The following is not legal,
Runnable r = new Runnable(); // can't instantiate interface

whereas the following is legal, because it’s instantiating an implementer of the Runnable interface (an anonymous implementation class):
Runnable r = new Runnable() { // curly brace, not semicolon
public void run() { }
};

Argument-Defined Anonymous Inner Classes

If you understood what we’ve covered so far in this chapter, then this last part will be a walk in the park. If you are still a little fuzzy on anonymous classes, however, then you should reread the previous sections.

Imagine the following scenario. You’re typing along, creating the Perfect Class, when you write code calling a method on a Class1 object, and that method takes an object of type Interface1 (an interface).

class MyComplicatedClass {
void do() {
Class1 b = new Class1();
b.doSomething(!!!);

//Actually the !!! mean nothing. We don't have any argument matching // the input required here so I put the !!! to make it logical

}
}
interface Interface1 {
void doSomethingElse();
}
class Class1 {
void doSomething(Interface1 f) { }
}

No problems here, except that you don’t have an object from a class that implements Interface1, and you can’t instantiate one, either, because you don’t even have a class that implements Interface1, let alone an instance of one. So you first need a class that implements Interface1, and then you need an instance of that class to pass to the Class1 class’s doSomething() method. Knowing the smart Java programmer that you are, you simply define an anonymous inner class, right inside the argument. That’s right, just where you least expect to find a class. And here’s what it looks like:

1. class MyComplicatedClass {
2. void do() {
3. Class1 b = new Class1();
4. b.doSomething(new Interface1() {
5. public void doSomethingElse() {
6. System.out.println("Hey!!!");
7. }
8. });
9. }
10. }
11.
12. interface Interface1 {
13. void doSomethingElse();
14. }
15. class Class1 {
16. void doSomething(Interface1 f) { }
17. }

All the action starts on line 4. We’re calling doSomething() on a Class1 object, but the method takes an instance that IS-A Interface1, where Interface1 is an interface. So we must make both an implementation class and an instance of that class, all right here in the argument to doSomething(). So that’s what we do. We write

new Interface1() {

to start the new class definition for the anonymous class that implements the Interface1 interface. Interface1 has a single method to implement, doSomethingElse(), so on lines 5, 6, and 7 we implement the doSomethingElse() method. Then on line 8 more strange syntax appears. The first curly brace closes off the new anonymous class definition. But don’t forget that this all happened as part of a method argument, so the close parenthesis, ), finishes off the method invocation, and then we must still end the statement that began on line 4, so we end with a semicolon. Study this syntax! You will see anonymous inner classes on the exam, and you’ll have to be very, very picky about the way they’re closed. If they’re argument local, they end like this:
});

but if they’re just regular anonymous classes, then they end like this:
};

Regardless, the syntax is not what you use in virtually any other part of Java, so be careful. Any question from any part of the exam might involve anonymous inner classes as part of the code.

Previous Chapter: Chapter 53 - Method Local Inner classes

Next Chapter: Chapter 55 - Static Inner classes

19 comments:

  1. This is great! It was really helpful!
    I have a programming exam comming up, and
    we didn't receive a decent book or anything.
    But thanks to this I finally understand
    anonymous inner classes, thank you :)

    ReplyDelete
  2. Its good effort. and easy to understand the concept,simple example program for understanding the concept clearly.

    keep it up...

    ReplyDelete
  3. It's a really, really nice post Anand, thank you very very much.

    ReplyDelete
  4. On anonymous inner classes and polymorphism example, there's no way at all to call the new inner class' method? (brake)

    ReplyDelete
  5. Excellent blog.Prior to reading this blog I had barely an idea about anonymous inner class ,but it's now quite clear.
    Great job !!,please keep it up.

    ReplyDelete
  6. Excellent Blog. Keep it up

    ReplyDelete
  7. very interesting and helpful

    ReplyDelete
  8. very good link........n very helpfull........thank you very much.......

    ReplyDelete
  9. superb!! i was breaking my head with the code in bruce eckels book. then i saw this. now i know what an anonymous inner class is. you could do something to make this site more visible in google search

    ReplyDelete
  10. Great tutorial, it is quite dufficult to fing good resources about anonymous inner classes.

    ReplyDelete
  11. Gr8 work.. Finally understood it..
    But u can improve Ur blog by properly formatting code snippets. Its very hard to understand the code if its not properly indented !! :)

    ReplyDelete
  12. Really useful, if only more programmers could explain stuff this clearly

    ReplyDelete
  13. dude thanks for your post, i have a small doubt, what if i have a requirement of calling car's drive()method from a other class

    ReplyDelete
    Replies
    1. You are welcome Vinoth.

      If you have such a requirement, you have to use normal classes because anonymous classes dont support this kind of behavior. In a normal class, all you got to do is instantiate the Car object and then do carObj.drive();

      Anand

      Delete

© 2013 by www.inheritingjava.blogspot.com. All rights reserved. No part of this blog or its contents may be reproduced or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission of the Author.

ShareThis

Google+ Followers

Followers