There is no function structural type in Java 8. But Java has always had first class objects. And in fact, they have been used as an alternative. Historically, due to the lack of first-class functions, what we have done so far is to wrap the function inside an object. These are the famous SAM types (single abstract method types).
So, instead of
function run() {}
Thread t = new Thread(run);
We do
Runnable run = new Runnable(){ public void run(){} };
Thread t = new Thread(run);
That is, we put the function inside an object in order to be able to pass it around as a value. So, first class objects have been an alternative solution for a long time.
The JDK 8 simply makes implementing this concept simpler, and they call this type of wrapper interfaces "Functional Interfaces" and offer some syntactic sugar to implement the wrapper objects.
Runnable run = () -> {};
Thread t = new Thread(run);
But ultimately, we are still using first-class objects. And they have similar properties to first-class functions. They encapsulate behavior, they can be passed as arguments and be returned as values.
In the lambda mailing list Brian Goetz gave a good explanation of some of the reasons that motivated this design.
Along the lines that we've been discussing today, here's a peek at
where we're heading. We explored the road of "maybe lambdas should
just be inner class instances, that would be really simple", but
eventually came to the position of "functions are a better direction
for the future of the language".
This exploration played out in stages: first internally before the EG
was formed, and then again when the EG discussed the issues. The
following is my position on the issue. Hopefully, this fills in some
of the gaps between what the spec currently says and what we say
about it.
The issues that have been raised about whether lambdas are objects or
not largely come down to philosophical questions like "what are
lambdas really", "why will Java benefit from lambdas", and ultimately
"how best to evolve the Java language and platform."
Oracle's position is that Java must evolve -- carefully, of course --
in order to remain competitive. This is, of course, a difficult
balancing act.
It is my belief that the best direction for evolving Java is to
encourage a more functional style of programming. The role of Lambda
is primarily to support the development and consumption of more
functional-like libraries; I've offered examples such as
filter-map-reduce to illustrate this direction.
There is plenty of evidence in the ecosystem to support the hypothesis
that, if given the tools to do so easily, object-oriented programmers
are ready to embrace functional techniques (such as immutability) and
work them into an object-oriented view of the world, and will write
better, less error-prone code as a result. Simply put, we believe the
best thing we can do for Java developers is to give them a gentle push
towards a more functional style of programming. We're not going to
turn Java into Haskell, nor even into Scala. But the direction is
clear.
Lambda is the down-payment on this evolution, but it is far from the
end of the story. The rest of the story isn't written yet, but
preserving our options are a key aspect of how we evaluate the
decisions we make here.
This is why I've been so dogged in my insistence that lambdas are not
objects. I believe the "lambdas are just objects" position, while
very comfortable and tempting, slams the door on a number of
potentially useful directions for language evolution.
As a single example, let's take function types. The lambda strawman
offered at devoxx had function types. I insisted we remove them, and
this made me unpopular. But my objection to function types was not
that I don't like function types -- I love function types -- but that
function types fought badly with an existing aspect of the Java type
system, erasure. Erased function types are the worst of both worlds.
So we removed this from the design.
But I am unwilling to say "Java never will have function types"
(though I recognize that Java may never have function types.) I
believe that in order to get to function types, we have to first deal
with erasure. That may, or may not be possible. But in a world of
reified structural types, function types start to make a lot more
sense.
The lambdas-are-objects view of the world conflicts with this possible
future. The lambdas-are-functions view of the world does not, and
preserving this flexibility is one of the points in favor of not
burdening lambdas with even the appearance of object-ness.
You might think that the current design is tightly tied to an object
box for lambdas -- SAM types -- making them effectively objects
anyway. But this has been carefully hidden from the surface area so
as to allow us to consider 'naked' lambdas in the future, or consider
other conversion contexts for lambdas, or integrate lambdas more
tightly into control constructs. We're not doing that now, and we
don't even have a concrete plan for doing so, but the ability to
possibly do that in the future is a critical part of the design.
I am optimistic about Java's future, but to move forward we sometimes
have to let go of some comfortable ideas. Lambdas-are-functions opens
doors. Lambdas-are-objects closes them. We prefer to see those doors
left open.