Inner Classes and Lambda Expressions
Inner Classes and Lambda Expressions
Taylor Hartman
March 2015
1 Inner Classes
Inner classes are just classes that are defined in other classes.
Example:
public class OuterClass {
//outer class variables
//outer class methods
Inner classes can be private or public, just like regular classes. Note: Inner and
outer classes have access to each others private members.
When/why would I use an inner class?
If you create a class only to be used in one other class, then you can make that class
an inner class of the outer class. For example, if we have a Business.java
class and it needs to make use of a helper class Employee.java, we can make
Employee an inner class. Essentially, if the other class is not going to be at all
useful for other classes, you can make it an inner class.
Other classes can access public inner classes, but I will leave you to look into
that more since as far as this class goes, we just want to focus on the basics of inner
classes.
1
An example of an inner class:
public class HelloWorldAnonymousClasses {
interface HelloWorld {
public void greet();
public void greetSomeone(String name);
}
englishGreeting.greet();
}
2
1.1 Anonymous Inner Classes
The answer to that question is Yes. There are situations where naming the inner
class is just a waste of space or time and its completely unnecessary. We call inner
classes we dont provide a name to Anonymous Classes. Taking the above example
of the EnglishGreeting class, below is an implementation of the same code
but with an anonymous class.
public class HelloWorldAnonymousClasses {
interface HelloWorld {
public void greet();
public void greetSomeone(String name);
}
The difference is subtle, but notice that instead of declaring a class and then
creating an object, we instead define the class in the instantiation of the object. So
when I want to create a HelloWorld object, I can just provide the definition I
want that object to have in-line with the creation of it.
Type referenceName = new Type() { //class implementation /};
Anonymous classes might seem pointless and you might be saying to yourself
Well thats all fine and dandy, but why do I care? When will this ever be useful?
The places Ive seen anonymous classes the most is in GUI and Swing applications.
We havent gotten to that part of the course yet, but creating GUI (Graphical User
Interface) applications involves creating helper classes like Listeners and Even-
tHandlers to handle responding and interacting with a user.
3
I will provide you with another example of an anonymous class. First, let me
introduce you to the Comparator interface. Comparators provide a comparison
function that imposes a total ordering on a set of objects. So lets say I have a bunch
of people. I can compare these people in a lot of different ways: by age, height,
weight, level of education, IQ, etc. Using a Comparator and just implementing the
compare method with however we want to compare is a lot easier than trying to
guess how many different ways I want to compare people. So now that we have a
little background, lets see this in action. I have a class Person.java and I want
to sort an array of Person objects by different means.
Person[] rosterArray = roster.toArray(new Person[roster.size()]);
So the sort method will sort the Person objects in rosterAsArray by the
ordering provided/defined by the object PersonAgeComparator.
I hope that you also remember that we could do this with and anonymous class.
The implementation is below, and is equivalent to the above code.
Arrays.sort(rosterAsArray, new Comparator<Person>() {
public int compare(Person a, Person b) {
return a.getBirthday().compareTo(b.getBirthday());
}
});
4
equivalent to the code presented further up using the inner class. Hopefully that ex-
ample shows you the usefulness of an inner class in a way that seems more useful
than just saying “Hello World.” Now lets discuss how confusing that code looks.
Using the anonymous class, we create a new Comparator and then provide an en-
tire class definition right there in the sort method. This is sometimes a problem
with anonymous classes. In our case, the implementation is very simple, we just
want to provide a definition for the compare method, but the syntax seems slightly
unclear and unwieldy. Luckily for us, the Java gods have smiled down upon as and
provided us a way to clean up this notation.
2 Lambda Expressions
Lambdas allow us to express instances of single-method classes in a cleaner way.
Before we go on I want to stress that lambdas are nothing more than just a syntactic
shortcut. A lambda can always be rewritten as an anonymous class. (NOTE: the
converse is not always true)
So lets take our anonymous class implementation of sorting our roster and show
you what a lambda looks like.
Arrays.sort(rosterAsArray,(Person a, Person b) ->
a.getBirthday().compareTo(b.getBirthday());
Note that all we did was take out the new Comparator¡Person¿() and return
and added in an -¿ (pronounced arrow token). So we see that a lambda is just
a shortcut for the anonymous class. The lambda and the anonymous class are
implementation-aly equivalent but syntactically different.
So heres a breakdown of the lambda syntax:
(Parameters separates by commas) -> body of the abstract
method
You might be a little weirded out by one thing at this point: where did the return
go? If you specify a single expression (which is what we did) in a lambda then the
Java runtime evaluates the expression and returns its value. We could alternatively
use a return statement, but a return statement is not an expression and you would
need to include the . This is illustrated below and is equivalent to the above lambda
expression:
Arrays.sort(rosterAsArray,(Person a, Person b) -> {
return a.getBirthday().compareTo(b.getBirthday();
});
So that is lambdas! Now the question is when can we use them? You can use a
5
lambda to define a single abstract method that is present in a functional interface.
3 Functional Interfaces
A functional interface is an interface that contains only one abstract method. Func-
tional interfaces provide target types for lambda expressions and method refer-
ences. Functional interfaces can be found in the java.util.function package. Func-
tional interfaces are slightly different from the regular interfaces we have seen up
until now. If you go look at any of the functional interfaces in the API you will
notice and probably be slightly bothered by the fact that these interfaces have meth-
ods that are defined in them. Functional interfaces can have many methods that are
already implemented. These methods are default methods and static methods. Im
not going to go into much detail about them because they arent really something
you need to be worried about. All you need to know is that they are already imple-
mented for you and you can use them if you want. In a functional interface there is
only one abstract method. This method is the target for the lambda expression.
Comparator is a functional interface and its abstract method is compare. We
have already been working with this interface and this method. I suggest you go
look at Comparator in the API and see how it has other static and default methods
but compare is the only abstract method.
How does Java know what Im trying to do when I use a Lambda?
As I mentioned above, the Arrays class has a sort method whose method sig-
nature is:
public static <T> void sort(T[] a, Comparator<? super T> c)
We know from our Java experience that if I were to pass something into the sort
method that wasnt an array and then a Comparator object, there would be an issue.
Java would yell at us and we would have to go fix it. So we know and Java knows
that the first parameter has to be an array and the second parameter has to be a
Comparator object. Now when we use the lambda to define the abstract method of
comparator, how does Java know thats what were trying to do? Well, Java knows
that the second parameter is a comparator, and it knows the -¿ means we are trying
to define a method, and since Comparator only has one abstract method that would
need to be defined, Java knows we must be defining and calling that method in
particular. This argument follows for all functional interfaces.