return new SomeModel(rs.getInt(1));
Listing 1-12. Example of JdbcTemplate usage with lambdas
jdbcTemplate.query("SELECT bar FROM Foo WHERE baz = ?",
ps -> ps.setString(1, "some value for baz"),
(rs, rowNum) -> new SomeModel(rs.getInt(1))
With Java 8, Java has opened up its syntactic purview. When Java started, it was a cutting-edge
implementation of a cutting-edge programming paradigm: object-oriented programming. Java went
solidly into object-oriented programming, which meant that you were to no longer think of “implementing
functions,” but of “defining behavior.” Conceptually, all activity within a program was the behavior of
an object, 9 with similar objects implementing interfaces. The theory is that this encourages reuse and
testability: a good object-oriented programming team would define discrete, extensible, well-exercised, and
well-tested implementations of these interfaces. Anonymous inner classes, like the ones we used above, are
not reusable and aren't discrete at all. They are therefore fighting against the object-oriented paradigm and
sacrificing its major advantages. 10
But if anonymous inner classes are so bad, why does everyone use them in this circumstance? The
reason is because the logic is extremely contextual and therefore not much eligible for reuse. Furthermore,
defining an additional type would be more obfuscating than clarifying by creating “spaghetti code”; the
call stack would wander into and out of a variety of source files, which makes it hard for the developer to
understand the program flow. These anonymous inner classes are therefore the best solution within the
object-oriented paradigm, but they are obviously not great.
The fundamental problem is that within the object-oriented paradigm, it is not possible to directly
express, “Give me a way to assign the parameters on the JDBC Statement instance I will create.” That is what
the JdbcTemplate wants, but that isn't an object-oriented kind of question. What the JdbcTemplate has to
do is define an interface, and the user has to define a function that fulfills that interface. This means that the
JdbcTemplate is asking, “Give me an object fulfilling a certain API contract that I can trigger to assign the
parameters on the JDBC Statement that I will create.” Since requiring an object requires a type, requiring an
object therefore requires the syntactic overhead of the anonymous inner class.
The lambdas in Java 8 actually step out of the object-oriented paradigm, and therefore allow the
syntax to express precisely what the JdbcTemplate is asking for. The functional paradigm does not create
the rich and descriptive API that the object-oriented program has, 11 but the trade-off is that the code itself
becomes much more succinct and self-expressive. This is the same trade-off used by many of the alternative
languages on Java's virtual machine, and now Java has joined that club. 12
9 Static methods are the obvious exception to this rule, although you can think of the static members of a class as
implementing a singleton object. This way of thinking is demonstrated best by Scala's “object” keyword.
10 It's worth noting at this point that inner classes—including anonymous inner classes—were not part of the Java 1.0
specification. They arrived in Java 1.1.
11 Is there any question what an implementation of the PreparedStatementSetter interface is supposed to do?
12 Because of Java's adamant object-oriented roots, the language itself is still a bit awkward with this trade-off: for
instance, the java.util.function documentation specifies that it's okay to refer to a lambda as “this function” instead
of “the function represented by this object.” Nonetheless, lambdas are a powerful feature borrowed from the functional
programming paradigm, and integrated well into Java 8.