You've been taught that every new class you write should go in a separate .java file named after the class, and generally that is true. But you can also define a class inside another class; this is called an inner class. Why would you want to do this? It has mostly to do with program organization. Perhaps the class relates only to the outer class (the class in which it is defined) and not appropriate for use by other classes.
Static Inner Classes
We could create a Tank class for storing fuel for a MotorVehicle, and because this would be different than other tanks (an oil tank or an army tank), we could define it inside the MotorVehicle class itself, creating a static inner class.
Non-Static Inner Classes
We can also create inner classes that are not static. These classes can only be instantiated in the context of an instance of the outer class. In other words, you cannot create one by itself; its outer class must be instantiated. An instance of a non-static inner class has access to all the instance variables and methods of the outer class. This is one way to create “helper functionality”.
Anonymous Classes
Java allows you to extend a class (or implement an interface) on the fly without creating a separate format class definition. The class is anonymous because it has no name, which implies that no one can make another instance of that class. Essentially you define the class and instantiate it in one fell swoop. Normally this is done to implement an abstract method on the fly for a utility class.
Consider an AbstractEngine that is defined in a separate class, requiring the implementation of a showWarning(…) method for indicating that the engine is overheating, for example. A MotorVehicle class could create an anonymous subclass of AbstractEngine, implementing the showWarning(…) method on the fly.
Because the anonymous class is defined in the scope of the MotorVehicle, it has access to all the variables and methods of the MotorVehicle instance, just like an inner class. Things get more interesting then if the MotorVehicle already has a way to display warnings to the user. In this case, the anonymous class can simply delegate to the MotorVehicle's functionality.
You can create anonymous implementations of interfaces on the fly as well. When learning about generics you learned how it could be useful to create a read-only, empty list and cast it to some generic type on the fly so that it could be used in various situations. Rather than creating a separate EmptyLinkedList<E> class, you could create an anonymous implementation of LinkedList<E> to use as the shared empty list instance.
A Class is a Class<T>
When you create a new FooBar class, the resulting object is an instance of FooBar, as you would expect.
final FooBar fooBar = new FooBar();
System.out.println(fooBar instanceof FooBar); //prints "true"
You also know that if FooBar has any static variables, they live independent of any instance of FooBar. That's because the FooBar class itself is an object! For every class (and interface) you access, from FooBar to Animal to Vehicle, Java will create an object to represent that class. The object representing the class is accessed via a .class member that is present for every class. For example, FooBar.class provides a reference to the object that represents the FooBar class.
Every object is an instance of some class, and in fact every class is an instance of the Class<T> class. Note that Class<T> uses generics. The generic type <T> refers to the type of the class, and you'll soon see how this can be useful.
Another useful method is java.lang.Class.isInstance(Object obj), which checks to see if some object is an instance of the given class. This method functions identically to the instanceof operator, with the added benefit that you can use it for some instance of a Class<> even if you don't know what class it is!
Casting Class<T> Instances
Once you know that an object is the instance of some Class<T>, you can cast the instance to type T using the java.lang.Class.cast(Object obj) method.
Getting a Class<T> from an Instance
There is another way to find a class object. If you only have a reference to an object, you can get a reference to that object's class instance by calling java.lang.Object.getClass(). This is possible because the method getClass() is defined in the java.lang.Object class, and every class extends from Object—even Class<T>!
final Truck truck = new Truck();
final Class<Truck> truckClass1 = Truck.class;
final Class<? extends Truck> truckClass2 = truck.getClass();
System.out.println(truckClass1 == truckClass2); //prints "true"
Review
In the Real World
Inner classes have their uses, but in real life, if an inner class is to be accessed publicly, a separate class may wind up being a better choice.
Self Evaluation
What is the difference between static and non-static inner classes?
How would you access a variable of an outer class from an inner class that shadowed the variable?
Class.class refers to an object that is an instance of what class?
Task
In your Booker application create a getPublicationsByType(…) method. One of its parameters will be a linked list, using generics to allow a linked list of any publication type. The second parameter will be a Class<>, but it must of a Publication or subclass. Pick out all the publications of the given type and return a new linked list (of the captured type of the class) containing only publications of that type. Here's how it the method might be called:
final LinkedList<Book> books = getPublicationsByType(publicationList, Book.class);
Create appropriate unit tests of getPublicationsByType(…), including the following
Create a list of books, magazines, and journals.
Call getPublicationsByType(publicationList, Periodical.class), storing the result in a LinkedList<Periodical>.
Ensure that the returns list is the expected size, and that it contains only periodicals.
Finally refactor each of your methods that prints a certain type of publication, such as printBooks(). Rather than searching through the list and printing the correct type of publication, delegate to your new getPublicationsByType(…) method to retrieve a list containing only publications of the correct type. Then iterate through the new list and print those publications with no further need to check types or perform any additional casting.